mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-25 23:45:58 +01:00
Allow region sharing
This commit is contained in:
parent
80775707ea
commit
2dc95fe02f
4 changed files with 105 additions and 35 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue