mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
[proof-of-concept] allow toplevel capture
Missing: - xwayland child windows - xwayland unmanaged windows, e.g. popups / menus / ... - xdg child window positioning - xdg subsurfaces (test-case: mate-terminal settings listboxes) - xdg popup positioning
This commit is contained in:
parent
259803178e
commit
6400b5203e
8 changed files with 82 additions and 0 deletions
|
|
@ -188,6 +188,13 @@ struct server {
|
|||
struct wlr_xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
|
||||
struct wl_listener xdg_toplevel_icon_set_icon;
|
||||
|
||||
struct {
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *manager;
|
||||
struct {
|
||||
struct wl_listener new_request;
|
||||
} on;
|
||||
} toplevel_capture;
|
||||
|
||||
struct wl_list views;
|
||||
struct wl_list unmanaged_surfaces;
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ struct view {
|
|||
char *title;
|
||||
char *app_id; /* WM_CLASS for xwayland windows */
|
||||
|
||||
struct {
|
||||
struct wlr_scene *scene;
|
||||
struct wlr_ext_image_capture_source_v1 *source;
|
||||
} capture;
|
||||
|
||||
bool mapped;
|
||||
bool been_mapped;
|
||||
enum lab_ssd_mode ssd_mode;
|
||||
|
|
@ -304,6 +309,7 @@ struct xdg_toplevel_view {
|
|||
/* Events unique to xdg-toplevel views */
|
||||
struct wl_listener set_app_id;
|
||||
struct wl_listener request_show_window_menu;
|
||||
struct wl_listener set_parent;
|
||||
struct wl_listener new_popup;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
|
|||
return;
|
||||
}
|
||||
|
||||
/* In support for ext-toplevel-capture */
|
||||
ext_toplevel->handle->data = view;
|
||||
|
||||
/* Client side requests */
|
||||
ext_toplevel->on.handle_destroy.notify = handle_handle_destroy;
|
||||
wl_signal_add(&ext_toplevel->handle->events.destroy, &ext_toplevel->on.handle_destroy);
|
||||
|
|
|
|||
35
src/server.c
35
src/server.c
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -423,6 +424,25 @@ handle_renderer_lost(struct wl_listener *listener, void *data)
|
|||
wlr_renderer_destroy(old_renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_toplevel_capture_request(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct server *server = wl_container_of(listener, server, toplevel_capture.on.new_request);
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data;
|
||||
struct view *view = request->toplevel_handle->data;
|
||||
assert(view);
|
||||
wlr_log(WLR_INFO, "Got request to capture toplevel %s", view->app_id);
|
||||
|
||||
if (!view->capture.source) {
|
||||
view->capture.source = wlr_ext_image_capture_source_v1_create_with_scene_node(
|
||||
&view->capture.scene->tree.node, server->wl_event_loop,
|
||||
server->allocator, server->renderer);
|
||||
}
|
||||
assert(view->capture.source);
|
||||
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
||||
request, view->capture.source);
|
||||
}
|
||||
|
||||
void
|
||||
server_init(struct server *server)
|
||||
{
|
||||
|
|
@ -656,6 +676,19 @@ server_init(struct server *server)
|
|||
wlr_screencopy_manager_v1_create(server->wl_display);
|
||||
wlr_ext_image_copy_capture_manager_v1_create(server->wl_display, 1);
|
||||
wlr_ext_output_image_capture_source_manager_v1_create(server->wl_display, 1);
|
||||
|
||||
server->toplevel_capture.manager =
|
||||
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(
|
||||
server->wl_display, 1);
|
||||
if (server->toplevel_capture.manager) {
|
||||
server->toplevel_capture.on.new_request.notify = handle_toplevel_capture_request;
|
||||
wl_signal_add(&server->toplevel_capture.manager->events.new_request,
|
||||
&server->toplevel_capture.on.new_request);
|
||||
} else {
|
||||
/* Allow safe removal on shutdown */
|
||||
wl_list_init(&server->toplevel_capture.on.new_request.link);
|
||||
}
|
||||
|
||||
wlr_data_control_manager_v1_create(server->wl_display);
|
||||
wlr_ext_data_control_manager_v1_create(server->wl_display,
|
||||
LAB_EXT_DATA_CONTROL_VERSION);
|
||||
|
|
@ -788,6 +821,8 @@ server_finish(struct server *server)
|
|||
server->drm_lease_request.notify = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&server->toplevel_capture.on.new_request.link);
|
||||
|
||||
wlr_backend_destroy(server->backend);
|
||||
wlr_allocator_destroy(server->allocator);
|
||||
|
||||
|
|
|
|||
|
|
@ -2570,6 +2570,8 @@ view_init(struct view *view)
|
|||
|
||||
view->title = xstrdup("");
|
||||
view->app_id = xstrdup("");
|
||||
|
||||
view->capture.scene = wlr_scene_create();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2596,6 +2598,8 @@ view_destroy(struct view *view)
|
|||
zfree(view->title);
|
||||
zfree(view->app_id);
|
||||
|
||||
wlr_scene_node_destroy(&view->capture.scene->tree.node);
|
||||
|
||||
if (view->foreign_toplevel) {
|
||||
foreign_toplevel_destroy(view->foreign_toplevel);
|
||||
view->foreign_toplevel = NULL;
|
||||
|
|
|
|||
|
|
@ -166,4 +166,6 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
|
|||
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
|
||||
node_descriptor_create(wlr_popup->base->surface->data,
|
||||
LAB_NODE_XDG_POPUP, view, /*data*/ NULL);
|
||||
|
||||
wlr_scene_xdg_surface_create(&view->capture.scene->tree, wlr_popup->base);
|
||||
}
|
||||
|
|
|
|||
24
src/xdg.c
24
src/xdg.c
|
|
@ -28,6 +28,8 @@
|
|||
#define LAB_XDG_SHELL_VERSION 6
|
||||
#define CONFIGURE_TIMEOUT_MS 100
|
||||
|
||||
static struct view *xdg_toplevel_view_get_root(struct view *view);
|
||||
|
||||
static struct xdg_toplevel_view *
|
||||
xdg_toplevel_view_from_view(struct view *view)
|
||||
{
|
||||
|
|
@ -377,6 +379,7 @@ handle_destroy(struct wl_listener *listener, void *data)
|
|||
/* Remove xdg-shell view specific listeners */
|
||||
wl_list_remove(&xdg_toplevel_view->set_app_id.link);
|
||||
wl_list_remove(&xdg_toplevel_view->request_show_window_menu.link);
|
||||
wl_list_remove(&xdg_toplevel_view->set_parent.link);
|
||||
wl_list_remove(&xdg_toplevel_view->new_popup.link);
|
||||
wl_list_remove(&view->commit.link);
|
||||
|
||||
|
|
@ -488,6 +491,23 @@ handle_request_show_window_menu(struct wl_listener *listener, void *data)
|
|||
menu_open_root(menu, cursor->x, cursor->y);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_set_parent(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct xdg_toplevel_view *xdg_toplevel_view = wl_container_of(
|
||||
listener, xdg_toplevel_view, set_parent);
|
||||
struct view *view = &xdg_toplevel_view->base;
|
||||
struct view *view_root = xdg_toplevel_view_get_root(view);
|
||||
if (view_root == view) {
|
||||
return;
|
||||
}
|
||||
struct wlr_scene_node *node, *tmp;
|
||||
wl_list_for_each_safe(node, tmp, &view->capture.scene->tree.children, link) {
|
||||
wlr_log(WLR_INFO, "moving capture scene node to view_root");
|
||||
wlr_scene_node_reparent(node, &view_root->capture.scene->tree);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_set_title(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -1050,6 +1070,9 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
|
|||
|
||||
view_connect_map(view, xdg_surface->surface);
|
||||
|
||||
struct view *root_view = xdg_toplevel_view_get_root(view);
|
||||
wlr_scene_xdg_surface_create(&root_view->capture.scene->tree, xdg_surface);
|
||||
|
||||
struct wlr_xdg_toplevel *toplevel = xdg_surface->toplevel;
|
||||
CONNECT_SIGNAL(toplevel, view, destroy);
|
||||
CONNECT_SIGNAL(toplevel, view, request_move);
|
||||
|
|
@ -1063,6 +1086,7 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
|
|||
/* Events specific to XDG toplevel views */
|
||||
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_app_id);
|
||||
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, request_show_window_menu);
|
||||
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_parent);
|
||||
CONNECT_SIGNAL(xdg_surface, xdg_toplevel_view, new_popup);
|
||||
|
||||
wl_list_insert(&server->views, &view->link);
|
||||
|
|
|
|||
|
|
@ -844,6 +844,7 @@ xwayland_view_map(struct view *view)
|
|||
return;
|
||||
}
|
||||
view->content_tree = tree;
|
||||
wlr_scene_subsurface_tree_create(&view->capture.scene->tree, view->surface);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue