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 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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue