support screenshare of single windows

Supersedes https://codeberg.org/dwl/dwl/pulls/1157.

Co-authored-by: Zuki Air <zukirust@gmail.com>
This commit is contained in:
Guido Cella
2026-09-12 10:28:05 +02:00
co-authored by Zuki Air
parent 721f70ea8b
commit fb4102b5ae
+47
View File
@@ -121,6 +121,12 @@ typedef struct {
} surface;
struct wlr_xdg_toplevel_decoration_v1 *decoration;
struct wlr_ext_foreign_toplevel_handle_v1 *foreign_toplevel_handle;
struct wlr_scene *image_capture_scene;
struct wlr_ext_image_capture_source_v1 *image_capture_source;
union {
struct wlr_scene_tree *image_capture_tree;
struct wlr_scene_surface *image_capture_scene_surface;
} capture;
struct wl_listener commit;
struct wl_listener map;
struct wl_listener maximize;
@@ -251,6 +257,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
static void arrangelayers(Monitor *m);
static void axisnotify(struct wl_listener *listener, void *data);
static void buttonpress(struct wl_listener *listener, void *data);
static void capturerequest(struct wl_listener *listener, void *data);
static void chvt(const Arg *arg);
static void checkidleinhibitor(struct wlr_surface *exclude);
static void cleanup(void);
@@ -386,6 +393,7 @@ static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
static struct wlr_output_power_manager_v1 *power_mgr;
static struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
static struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *ext_foreign_toplevel_image_capture_source_manager_v1;
static struct wlr_pointer_constraints_v1 *pointer_constraints;
static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
@@ -440,6 +448,7 @@ static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape};
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
static struct wl_listener start_drag = {.notify = startdrag};
static struct wl_listener new_session_lock = {.notify = locksession};
static struct wl_listener new_foreign_toplevel_capture_request = {.notify = capturerequest};
#ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data);
@@ -688,6 +697,23 @@ buttonpress(struct wl_listener *listener, void *data)
event->time_msec, event->button, event->state);
}
void
capturerequest(struct wl_listener *listener, void *data)
{
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data;
Client *view = request->toplevel_handle->data;
if (!view->image_capture_source) {
view->image_capture_source = wlr_ext_image_capture_source_v1_create_with_scene_node(
&view->image_capture_scene->tree.node, event_loop, alloc, drw);
if (!view->image_capture_source)
return;
}
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
request, view->image_capture_source);
}
void
chvt(const Arg *arg)
{
@@ -800,6 +826,7 @@ cleanuplisteners(void)
wl_list_remove(&request_start_drag.link);
wl_list_remove(&start_drag.link);
wl_list_remove(&new_session_lock.link);
wl_list_remove(&new_foreign_toplevel_capture_request.link);
#ifdef XWAYLAND
wl_list_remove(&new_xwayland_surface.link);
wl_list_remove(&xwayland_ready.link);
@@ -1838,6 +1865,14 @@ mapnotify(struct wl_listener *listener, void *data)
c->foreign_toplevel_handle = wlr_ext_foreign_toplevel_handle_v1_create(
foreign_toplevel_list, &foreign_toplevel_state);
c->foreign_toplevel_handle->data = c;
c->image_capture_scene = wlr_scene_create();
if (c->type == XDGShell)
c->capture.image_capture_tree = wlr_scene_xdg_surface_create(&c->image_capture_scene->tree, c->surface.xdg);
#ifdef XWAYLAND
else
c->capture.image_capture_scene_surface = wlr_scene_surface_create(&c->image_capture_scene->tree, c->surface.xwayland->surface);
#endif
/* Set initial monitor, tags, floating status, and focus:
* we always consider floating, clients that have parent and thus
@@ -2630,6 +2665,10 @@ setup(void)
wlr_scene_node_set_enabled(&locked_bg->node, 0);
foreign_toplevel_list = wlr_ext_foreign_toplevel_list_v1_create(dpy,1);
ext_foreign_toplevel_image_capture_source_manager_v1 =
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(dpy, 1);
wl_signal_add(&ext_foreign_toplevel_image_capture_source_manager_v1->events.new_request,
&new_foreign_toplevel_capture_request);
/* Use decoration protocols to negotiate server-side decorations */
wlr_server_decoration_manager_set_default_mode(
@@ -2898,6 +2937,14 @@ unmapnotify(struct wl_listener *listener, void *data)
wlr_ext_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel_handle);
c->foreign_toplevel_handle = NULL;
}
#ifdef XWAYLAND
if (c->type != XDGShell && c->capture.image_capture_scene_surface) {
wlr_scene_node_destroy(&c->capture.image_capture_scene_surface->buffer->node);
c->capture.image_capture_scene_surface = NULL;
}
#endif
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
wlr_scene_node_destroy(&c->scene->node);
client_surface(c)->data = NULL;
printstatus();