Add support for toplevel capture

This commit is contained in:
Mental-Vortex 2026-02-05 01:53:46 +08:00
parent 918c3290fc
commit f1ac8f6008
6 changed files with 52 additions and 0 deletions

View file

@ -284,6 +284,9 @@ struct server {
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list; struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *ext_foreign_toplevel_image_capture_source_manager_v1;
struct wl_listener new_foreign_toplevel_capture_request;
struct wlr_drm_lease_v1_manager *drm_lease_manager; struct wlr_drm_lease_v1_manager *drm_lease_manager;
struct wl_listener drm_lease_request; struct wl_listener drm_lease_request;

View file

@ -168,6 +168,9 @@ struct view {
struct wlr_scene_tree *scene_tree; struct wlr_scene_tree *scene_tree;
struct wlr_scene_tree *content_tree; /* may be NULL for unmapped view */ struct wlr_scene_tree *content_tree; /* may be NULL for unmapped view */
struct wlr_scene *image_capture_scene;
struct wlr_ext_image_capture_source_v1 *image_capture_source;
/* These are never NULL and an empty string is set instead. */ /* These are never NULL and an empty string is set instead. */
char *title; char *title;
char *app_id; /* WM_CLASS for xwayland windows */ char *app_id; /* WM_CLASS for xwayland windows */
@ -300,6 +303,8 @@ struct xdg_toplevel_view {
/* Optional black background fill behind fullscreen view */ /* Optional black background fill behind fullscreen view */
struct wlr_scene_rect *fullscreen_bg; struct wlr_scene_rect *fullscreen_bg;
struct wlr_scene_tree *image_capture_tree;
/* Events unique to xdg-toplevel views */ /* Events unique to xdg-toplevel views */
struct wl_listener set_app_id; struct wl_listener set_app_id;
struct wl_listener request_show_window_menu; struct wl_listener request_show_window_menu;

View file

@ -75,6 +75,8 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
return; return;
} }
ext_toplevel->handle->data = view;
/* Client side requests */ /* Client side requests */
ext_toplevel->on.handle_destroy.notify = handle_handle_destroy; ext_toplevel->on.handle_destroy.notify = handle_handle_destroy;
wl_signal_add(&ext_toplevel->handle->events.destroy, &ext_toplevel->on.handle_destroy); wl_signal_add(&ext_toplevel->handle->events.destroy, &ext_toplevel->on.handle_destroy);

View file

@ -424,6 +424,25 @@ handle_renderer_lost(struct wl_listener *listener, void *data)
wlr_renderer_destroy(old_renderer); wlr_renderer_destroy(old_renderer);
} }
static void
handle_new_foreign_toplevel_capture_request(struct wl_listener *listener, void *data) {
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data;
struct view *view = request->toplevel_handle->data;
struct server *server = wl_container_of(listener, server,
new_foreign_toplevel_capture_request);
if (view->image_capture_source == NULL) {
view->image_capture_source = wlr_ext_image_capture_source_v1_create_with_scene_node(
&view->image_capture_scene->tree.node,server->wl_event_loop,server->allocator,server->renderer);
if (view->image_capture_source == NULL) {
wlr_log(WLR_ERROR, "Failed to create image capture source");
return;
}
}
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(request, view->image_capture_source);
}
void void
server_init(struct server *server) server_init(struct server *server)
{ {
@ -671,6 +690,12 @@ server_init(struct server *server)
wlr_fractional_scale_manager_v1_create(server->wl_display, wlr_fractional_scale_manager_v1_create(server->wl_display,
LAB_WLR_FRACTIONAL_SCALE_V1_VERSION); LAB_WLR_FRACTIONAL_SCALE_V1_VERSION);
server->ext_foreign_toplevel_image_capture_source_manager_v1 =
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(server->wl_display, 1);
server->new_foreign_toplevel_capture_request.notify = handle_new_foreign_toplevel_capture_request;
wl_signal_add(&server->ext_foreign_toplevel_image_capture_source_manager_v1->events.new_request,
&server->new_foreign_toplevel_capture_request);
idle_manager_create(server->wl_display); idle_manager_create(server->wl_display);
server->relative_pointer_manager = wlr_relative_pointer_manager_v1_create( server->relative_pointer_manager = wlr_relative_pointer_manager_v1_create(
@ -788,6 +813,7 @@ server_finish(struct server *server)
wl_list_remove(&server->new_constraint.link); wl_list_remove(&server->new_constraint.link);
wl_list_remove(&server->output_power_manager_set_mode.link); wl_list_remove(&server->output_power_manager_set_mode.link);
wl_list_remove(&server->tearing_new_object.link); wl_list_remove(&server->tearing_new_object.link);
wl_list_remove(&server->new_foreign_toplevel_capture_request.link);
if (server->drm_lease_request.notify) { if (server->drm_lease_request.notify) {
wl_list_remove(&server->drm_lease_request.link); wl_list_remove(&server->drm_lease_request.link);
server->drm_lease_request.notify = NULL; server->drm_lease_request.notify = NULL;

View file

@ -2525,6 +2525,12 @@ view_init(struct view *view)
wl_signal_init(&view->events.set_icon); wl_signal_init(&view->events.set_icon);
wl_signal_init(&view->events.destroy); wl_signal_init(&view->events.destroy);
view->image_capture_scene = wlr_scene_create();
if (view->image_capture_scene == NULL) {
wlr_log(WLR_ERROR, "not image_capture_scene");
}
view->image_capture_scene->restack_xwayland_surfaces = false;
view->title = xstrdup(""); view->title = xstrdup("");
view->app_id = xstrdup(""); view->app_id = xstrdup("");
} }
@ -2593,6 +2599,11 @@ view_destroy(struct view *view)
view->scene_tree = NULL; view->scene_tree = NULL;
} }
if (view->image_capture_scene) {
wlr_scene_node_destroy(&view->image_capture_scene->tree.node);
view->image_capture_scene = NULL;
}
assert(wl_list_empty(&view->events.new_app_id.listener_list)); assert(wl_list_empty(&view->events.new_app_id.listener_list));
assert(wl_list_empty(&view->events.new_title.listener_list)); assert(wl_list_empty(&view->events.new_title.listener_list));
assert(wl_list_empty(&view->events.new_outputs.listener_list)); assert(wl_list_empty(&view->events.new_outputs.listener_list));

View file

@ -1030,6 +1030,11 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
free(xdg_toplevel_view); free(xdg_toplevel_view);
return; return;
} }
xdg_toplevel_view->image_capture_tree =
wlr_scene_xdg_surface_create(&view->image_capture_scene->tree,
xdg_surface);
view->content_tree = tree; view->content_tree = tree;
node_descriptor_create(&view->scene_tree->node, node_descriptor_create(&view->scene_tree->node,
LAB_NODE_VIEW, view, /*data*/ NULL); LAB_NODE_VIEW, view, /*data*/ NULL);