Allow region sharing

This commit is contained in:
vaxerski 2022-12-03 22:42:21 +00:00
parent 80775707ea
commit 2dc95fe02f
4 changed files with 105 additions and 35 deletions

View File

@ -130,6 +130,27 @@ struct xdpw_screencast_context {
struct wl_list screencast_instances;
};
struct xdpw_wlr_output {
struct wl_list link;
uint32_t id;
struct wl_output *output;
struct zxdg_output_v1 *xdg_output;
char *make;
char *model;
char *name;
int width;
int height;
float framerate;
};
struct xdpw_share {
struct xdpw_wlr_output *output;
int x;
int y;
int w;
int h;
};
struct xdpw_screencast_instance {
// list
struct wl_list link;
@ -154,7 +175,7 @@ struct xdpw_screencast_instance {
// wlroots
struct zwlr_screencopy_frame_v1 *frame_callback;
struct xdpw_wlr_output *target_output;
struct xdpw_share target;
uint32_t max_framerate;
struct zwlr_screencopy_frame_v1 *wlr_frame;
struct xdpw_screencopy_frame_info screencopy_frame_info[2];
@ -168,19 +189,6 @@ struct xdpw_screencast_instance {
struct fps_limit_state fps_limit;
};
struct xdpw_wlr_output {
struct wl_list link;
uint32_t id;
struct wl_output *output;
struct zxdg_output_v1 *xdg_output;
char *make;
char *model;
char *name;
int width;
int height;
float framerate;
};
void randname(char *buf);
struct gbm_device *xdpw_gbm_device_create(drmDevice *device);
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,

View File

@ -25,7 +25,7 @@ struct xdpw_wlr_output *xdpw_wlr_output_find_by_name(struct wl_list *output_list
struct xdpw_wlr_output *xdpw_wlr_output_first(struct wl_list *output_list);
struct xdpw_wlr_output *xdpw_wlr_output_find(struct xdpw_screencast_context *ctx,
struct wl_output *out, uint32_t id);
struct xdpw_wlr_output *xdpw_wlr_output_chooser(struct xdpw_screencast_context *ctx);
struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx);
void xdpw_wlr_frame_finish(struct xdpw_screencast_instance *cast);
void xdpw_wlr_frame_start(struct xdpw_screencast_instance *cast);

View File

@ -48,7 +48,7 @@ void exec_with_shell(char *command) {
}
void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
struct xdpw_screencast_instance *cast, struct xdpw_wlr_output *out, bool with_cursor) {
struct xdpw_screencast_instance *cast, struct xdpw_share out, bool with_cursor) {
// only run exec_before if there's no other instance running that already ran it
if (wl_list_empty(&ctx->screencast_instances)) {
@ -60,12 +60,12 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
}
cast->ctx = ctx;
cast->target_output = out;
cast->target = out;
if (ctx->state->config->screencast_conf.max_fps > 0) {
cast->max_framerate = ctx->state->config->screencast_conf.max_fps < (uint32_t)out->framerate ?
ctx->state->config->screencast_conf.max_fps : (uint32_t)out->framerate;
cast->max_framerate = ctx->state->config->screencast_conf.max_fps < (uint32_t)out.output->framerate ?
ctx->state->config->screencast_conf.max_fps : (uint32_t)out.output->framerate;
} else {
cast->max_framerate = (uint32_t)out->framerate;
cast->max_framerate = (uint32_t)out.output->framerate;
}
cast->framerate = cast->max_framerate;
cast->with_cursor = with_cursor;
@ -116,9 +116,9 @@ bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *ses
output->make, output->model, output->id, output->name);
}
struct xdpw_wlr_output *out;
out = xdpw_wlr_output_chooser(ctx);
if (!out) {
struct xdpw_share out;
out = xdpw_wlr_chooser(ctx);
if (!out.output) {
logprint(ERROR, "wlroots: no output found");
return false;
}
@ -153,7 +153,7 @@ bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *ses
out, with_cursor);
}
logprint(INFO, "wlroots: output: %s",
sess->screencast_instance->target_output->name);
sess->screencast_instance->target.output->name);
return true;

View File

@ -16,6 +16,7 @@
#include <assert.h>
#include <wayland-client-protocol.h>
#include <xf86drm.h>
#include <string.h>
#include "screencast.h"
#include "pipewire_screencast.h"
@ -249,8 +250,16 @@ static const struct zwlr_screencopy_frame_v1_listener wlr_frame_listener = {
};
void xdpw_wlr_register_cb(struct xdpw_screencast_instance *cast) {
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output(
cast->ctx->screencopy_manager, cast->with_cursor, cast->target_output->output);
if (cast->target.x != -1 && cast->target.y != -1 && cast->target.w != -1 && cast->target.h != -1) {
// capture region
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output_region(
cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output, cast->target.x,
cast->target.y, cast->target.w, cast->target.h);
} else {
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output(
cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output);
}
zwlr_screencopy_frame_v1_add_listener(cast->frame_callback,
&wlr_frame_listener, cast);
@ -333,8 +342,8 @@ static void wlr_init_xdg_outputs(struct xdpw_screencast_context *ctx) {
}
}
struct xdpw_wlr_output *xdpw_wlr_output_chooser(struct xdpw_screencast_context *ctx) {
char result[1024];
struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) {
char result[1024];
FILE *fp;
char buf[1024];
@ -351,27 +360,80 @@ struct xdpw_wlr_output *xdpw_wlr_output_chooser(struct xdpw_screencast_context *
pclose(fp);
// great, let's parse it.
// TODO: window & region
struct xdpw_share res = {NULL, -1, -1, -1, -1};
// TODO: window & region
if (strncmp(result, "screen:", 7) == 0) {
// find
// find output
char* display_name = malloc(strlen(result) - 7);
strncpy(display_name, result + 7, strlen(result) - 8);
display_name[strlen(result) - 8] = 0;
struct xdpw_wlr_output* out;
bool found = false;
wl_list_for_each(out, &ctx->output_list, link) {
if (strcmp(out->name, display_name) == 0) {
found = true;
break;
}
}
free(display_name);
return out;
if (!found)
return res;
res.output = out;
return res;
} else if (strncmp(result, "region:", 7) == 0) {
// find output
int atPos = 0;
for (int i = 0; i < (int)strlen(result); ++i) {
if (result[i] == '@'){
atPos = i;
break;
}
}
char *display_name = malloc(atPos - 6);
strncpy(display_name, result + 7, atPos - 7);
display_name[atPos - 7] = 0;
struct xdpw_wlr_output *out;
wl_list_for_each(out, &ctx->output_list, link) {
if (strcmp(out->name, display_name) == 0) {
break;
}
}
// then get coords
int coordno = 0;
int coords[4] = {-1, -1, -1, -1};
int coordbegin = 7 + strlen(display_name) + 1;
for (int i = 7 + strlen(display_name) + 1; i < (int)strlen(result); ++i) {
if (result[i] == ',' || result[i] == '@' || i + 1 == (int)strlen(result)) {
char* entire = malloc(i - coordbegin + 1);
strncpy(entire, result + coordbegin, i - coordbegin);
entire[i - coordbegin] = 0;
coords[coordno] = strtol(entire, NULL, 10);
free(entire);
coordno++;
coordbegin = i + 1;
i++;
}
}
free(display_name);
struct xdpw_share res2 = {out, coords[0], coords[1], coords[2], coords[3]};
return res2;
} else {
return NULL;
}
return res;
}
return res;
}
struct xdpw_wlr_output *xdpw_wlr_output_first(struct wl_list *output_list) {
@ -644,7 +706,7 @@ static void wlr_registry_handle_remove(void *data, struct wl_registry *reg,
logprint(DEBUG, "wlroots: output removed (%s)", output->name);
struct xdpw_screencast_instance *cast, *tmp;
wl_list_for_each_safe(cast, tmp, &ctx->screencast_instances, link) {
if (cast->target_output == output) {
if (cast->target.output == output) {
// screencopy might be in process for this instance
wlr_frame_free(cast);
// instance might be waiting for wakeup by the frame limiter