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 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 { struct xdpw_screencast_instance {
// list // list
struct wl_list link; struct wl_list link;
@ -154,7 +175,7 @@ struct xdpw_screencast_instance {
// wlroots // wlroots
struct zwlr_screencopy_frame_v1 *frame_callback; struct zwlr_screencopy_frame_v1 *frame_callback;
struct xdpw_wlr_output *target_output; struct xdpw_share target;
uint32_t max_framerate; uint32_t max_framerate;
struct zwlr_screencopy_frame_v1 *wlr_frame; struct zwlr_screencopy_frame_v1 *wlr_frame;
struct xdpw_screencopy_frame_info screencopy_frame_info[2]; struct xdpw_screencopy_frame_info screencopy_frame_info[2];
@ -168,19 +189,6 @@ struct xdpw_screencast_instance {
struct fps_limit_state fps_limit; 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); void randname(char *buf);
struct gbm_device *xdpw_gbm_device_create(drmDevice *device); struct gbm_device *xdpw_gbm_device_create(drmDevice *device);
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast, 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_first(struct wl_list *output_list);
struct xdpw_wlr_output *xdpw_wlr_output_find(struct xdpw_screencast_context *ctx, struct xdpw_wlr_output *xdpw_wlr_output_find(struct xdpw_screencast_context *ctx,
struct wl_output *out, uint32_t id); 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_finish(struct xdpw_screencast_instance *cast);
void xdpw_wlr_frame_start(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, 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 // only run exec_before if there's no other instance running that already ran it
if (wl_list_empty(&ctx->screencast_instances)) { 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->ctx = ctx;
cast->target_output = out; cast->target = out;
if (ctx->state->config->screencast_conf.max_fps > 0) { if (ctx->state->config->screencast_conf.max_fps > 0) {
cast->max_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->framerate; ctx->state->config->screencast_conf.max_fps : (uint32_t)out.output->framerate;
} else { } else {
cast->max_framerate = (uint32_t)out->framerate; cast->max_framerate = (uint32_t)out.output->framerate;
} }
cast->framerate = cast->max_framerate; cast->framerate = cast->max_framerate;
cast->with_cursor = with_cursor; 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); output->make, output->model, output->id, output->name);
} }
struct xdpw_wlr_output *out; struct xdpw_share out;
out = xdpw_wlr_output_chooser(ctx); out = xdpw_wlr_chooser(ctx);
if (!out) { if (!out.output) {
logprint(ERROR, "wlroots: no output found"); logprint(ERROR, "wlroots: no output found");
return false; return false;
} }
@ -153,7 +153,7 @@ bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *ses
out, with_cursor); out, with_cursor);
} }
logprint(INFO, "wlroots: output: %s", logprint(INFO, "wlroots: output: %s",
sess->screencast_instance->target_output->name); sess->screencast_instance->target.output->name);
return true; return true;

View file

@ -16,6 +16,7 @@
#include <assert.h> #include <assert.h>
#include <wayland-client-protocol.h> #include <wayland-client-protocol.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <string.h>
#include "screencast.h" #include "screencast.h"
#include "pipewire_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) { 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, zwlr_screencopy_frame_v1_add_listener(cast->frame_callback,
&wlr_frame_listener, cast); &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) { struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) {
char result[1024]; char result[1024];
FILE *fp; FILE *fp;
char buf[1024]; char buf[1024];
@ -351,27 +360,80 @@ struct xdpw_wlr_output *xdpw_wlr_output_chooser(struct xdpw_screencast_context *
pclose(fp); pclose(fp);
// great, let's parse it. // 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) { if (strncmp(result, "screen:", 7) == 0) {
// find // find output
char* display_name = malloc(strlen(result) - 7); char* display_name = malloc(strlen(result) - 7);
strncpy(display_name, result + 7, strlen(result) - 8); strncpy(display_name, result + 7, strlen(result) - 8);
display_name[strlen(result) - 8] = 0; display_name[strlen(result) - 8] = 0;
struct xdpw_wlr_output* out; struct xdpw_wlr_output* out;
bool found = false;
wl_list_for_each(out, &ctx->output_list, link) { wl_list_for_each(out, &ctx->output_list, link) {
if (strcmp(out->name, display_name) == 0) { if (strcmp(out->name, display_name) == 0) {
found = true;
break; break;
} }
} }
free(display_name); 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 { } else {
return NULL; return res;
} }
return res;
} }
struct xdpw_wlr_output *xdpw_wlr_output_first(struct wl_list *output_list) { 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); logprint(DEBUG, "wlroots: output removed (%s)", output->name);
struct xdpw_screencast_instance *cast, *tmp; struct xdpw_screencast_instance *cast, *tmp;
wl_list_for_each_safe(cast, tmp, &ctx->screencast_instances, link) { 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 // screencopy might be in process for this instance
wlr_frame_free(cast); wlr_frame_free(cast);
// instance might be waiting for wakeup by the frame limiter // instance might be waiting for wakeup by the frame limiter