mirror of
https://github.com/labwc/labwc.git
synced 2026-04-07 08:21:20 -04:00
Merge d333ed5c9f into c9b4da2ce2
This commit is contained in:
commit
601a94a540
11 changed files with 178 additions and 2 deletions
|
|
@ -62,7 +62,11 @@
|
||||||
#define BOUNDED_INT(a) ((a) < INT_MAX && (a) > INT_MIN)
|
#define BOUNDED_INT(a) ((a) < INT_MAX && (a) > INT_MIN)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) \
|
#define _LAB_CALC_WLR_VERSION_NUM(major, minor, micro) (((major) << 16) | ((minor) << 8) | (micro))
|
||||||
(WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro)))
|
|
||||||
|
#define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) ( \
|
||||||
|
server.wlr_version >= _LAB_CALC_WLR_VERSION_NUM(major, minor, micro))
|
||||||
|
|
||||||
|
#define LAB_WLR_VERSION_LOWER(major, minor, micro) (!LAB_WLR_VERSION_AT_LEAST(major, minor, micro))
|
||||||
|
|
||||||
#endif /* LABWC_MACROS_H */
|
#endif /* LABWC_MACROS_H */
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,8 @@ struct seat {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct server {
|
struct server {
|
||||||
|
uint32_t wlr_version;
|
||||||
|
|
||||||
struct wl_display *wl_display;
|
struct wl_display *wl_display;
|
||||||
struct wl_event_loop *wl_event_loop; /* Can be used for timer events */
|
struct wl_event_loop *wl_event_loop; /* Can be used for timer events */
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
|
|
@ -187,6 +189,13 @@ struct server {
|
||||||
struct wlr_xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
|
struct wlr_xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
|
||||||
struct wl_listener xdg_toplevel_icon_set_icon;
|
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;
|
||||||
|
|
||||||
/* front to back order */
|
/* front to back order */
|
||||||
struct wl_list views;
|
struct wl_list views;
|
||||||
uint64_t next_view_creation_id;
|
uint64_t next_view_creation_id;
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,12 @@ struct view {
|
||||||
char *title;
|
char *title;
|
||||||
char *app_id; /* WM_CLASS for xwayland windows */
|
char *app_id; /* WM_CLASS for xwayland windows */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wlr_scene *scene;
|
||||||
|
struct wlr_ext_image_capture_source_v1 *source;
|
||||||
|
struct wl_listener on_capture_source_destroy;
|
||||||
|
} capture;
|
||||||
|
|
||||||
bool mapped;
|
bool mapped;
|
||||||
bool been_mapped;
|
bool been_mapped;
|
||||||
uint64_t creation_id;
|
uint64_t creation_id;
|
||||||
|
|
@ -318,6 +324,7 @@ struct xdg_toplevel_view {
|
||||||
/* 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;
|
||||||
|
struct wl_listener set_parent;
|
||||||
struct wl_listener new_popup;
|
struct wl_listener new_popup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,9 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In support for ext-toplevel-capture */
|
||||||
|
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);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "common/fd-util.h"
|
#include "common/fd-util.h"
|
||||||
#include "common/font.h"
|
#include "common/font.h"
|
||||||
|
#include "common/macros.h"
|
||||||
#include "common/spawn.h"
|
#include "common/spawn.h"
|
||||||
#include "config/rcxml.h"
|
#include "config/rcxml.h"
|
||||||
#include "config/session.h"
|
#include "config/session.h"
|
||||||
|
|
@ -164,6 +165,12 @@ main(int argc, char *argv[])
|
||||||
char *primary_client = NULL;
|
char *primary_client = NULL;
|
||||||
enum wlr_log_importance verbosity = WLR_ERROR;
|
enum wlr_log_importance verbosity = WLR_ERROR;
|
||||||
|
|
||||||
|
server.wlr_version = _LAB_CALC_WLR_VERSION_NUM(
|
||||||
|
wlr_version_get_major(),
|
||||||
|
wlr_version_get_minor(),
|
||||||
|
wlr_version_get_micro()
|
||||||
|
);
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while (1) {
|
while (1) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
|
||||||
53
src/output.c
53
src/output.c
|
|
@ -51,6 +51,36 @@
|
||||||
#include <wlr/backend/session.h>
|
#include <wlr/backend/session.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Partial workaround for toplevel capture on wlroots 0.20.0
|
||||||
|
* Note that even with this workaround the capture itself might still stall.
|
||||||
|
*
|
||||||
|
* See https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5315
|
||||||
|
*
|
||||||
|
* TODO: Remove once we start tracking wlroots 0.21.x
|
||||||
|
* or labwc depends on wlroots >= 0.20.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_compositor.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
workaround_frame_done_iter(struct wlr_scene_buffer *buffer, int sx, int sy, void *data)
|
||||||
|
{
|
||||||
|
if (!buffer->primary_output) {
|
||||||
|
/* Catches hidden views, e.g. completely covered or disabled */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
if (!scene_surface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_surface_send_frame_done(scene_surface->surface, (struct timespec *)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Workaround for toplevel capture end */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
output_get_tearing_allowance(struct output *output)
|
output_get_tearing_allowance(struct output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -121,6 +151,29 @@ handle_output_frame(struct wl_listener *listener, void *data)
|
||||||
struct timespec now = { 0 };
|
struct timespec now = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
wlr_scene_output_send_frame_done(output->scene_output, &now);
|
wlr_scene_output_send_frame_done(output->scene_output, &now);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for toplevel capture on wlroots 0.20.0
|
||||||
|
*
|
||||||
|
* TODO: Remove once we start tracking wlroots 0.21.x
|
||||||
|
* or labwc depends on wlroots >= 0.20.1
|
||||||
|
*/
|
||||||
|
if (LAB_WLR_VERSION_LOWER(0, 20, 1)) {
|
||||||
|
struct view *view;
|
||||||
|
wl_list_for_each(view, &server.views, link) {
|
||||||
|
if (view->capture.source) {
|
||||||
|
if (!view_on_output(view, output)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* view might still be covered / disabled,
|
||||||
|
* but the iterator takes care of that.
|
||||||
|
*/
|
||||||
|
wlr_scene_node_for_each_buffer(&view->content_tree->node,
|
||||||
|
workaround_frame_done_iter, &now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
59
src/server.c
59
src/server.c
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
@ -428,6 +429,49 @@ handle_renderer_lost(struct wl_listener *listener, void *data)
|
||||||
wlr_renderer_destroy(old_renderer);
|
wlr_renderer_destroy(old_renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_toplevel_capture_source_destroy(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct view *view = wl_container_of(listener, view, capture.on_capture_source_destroy);
|
||||||
|
assert(view->capture.source);
|
||||||
|
view->capture.source = NULL;
|
||||||
|
wl_list_remove(&listener->link);
|
||||||
|
wl_list_init(&listener->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_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;
|
||||||
|
assert(view);
|
||||||
|
wlr_log(WLR_DEBUG, "Capturing 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);
|
||||||
|
|
||||||
|
view->capture.on_capture_source_destroy.notify =
|
||||||
|
handle_toplevel_capture_source_destroy;
|
||||||
|
wl_signal_add(&view->capture.source->events.destroy,
|
||||||
|
&view->capture.on_capture_source_destroy);
|
||||||
|
}
|
||||||
|
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
||||||
|
request, view->capture.source);
|
||||||
|
|
||||||
|
if (LAB_WLR_VERSION_LOWER(0, 20, 1)) {
|
||||||
|
/*
|
||||||
|
* Work around a memory leak in wlroots.
|
||||||
|
* See https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5328
|
||||||
|
*
|
||||||
|
* TODO: remove once we start tracking wlroots 0.21.x or depend on >= 0.20.1
|
||||||
|
*/
|
||||||
|
free(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_init(void)
|
server_init(void)
|
||||||
{
|
{
|
||||||
|
|
@ -666,6 +710,19 @@ server_init(void)
|
||||||
wlr_screencopy_manager_v1_create(server.wl_display);
|
wlr_screencopy_manager_v1_create(server.wl_display);
|
||||||
wlr_ext_image_copy_capture_manager_v1_create(server.wl_display, 1);
|
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);
|
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_data_control_manager_v1_create(server.wl_display);
|
||||||
wlr_ext_data_control_manager_v1_create(server.wl_display,
|
wlr_ext_data_control_manager_v1_create(server.wl_display,
|
||||||
LAB_EXT_DATA_CONTROL_VERSION);
|
LAB_EXT_DATA_CONTROL_VERSION);
|
||||||
|
|
@ -800,6 +857,8 @@ server_finish(void)
|
||||||
server.drm_lease_request.notify = NULL;
|
server.drm_lease_request.notify = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_remove(&server.toplevel_capture.on.new_request.link);
|
||||||
|
|
||||||
wlr_backend_destroy(server.backend);
|
wlr_backend_destroy(server.backend);
|
||||||
wlr_allocator_destroy(server.allocator);
|
wlr_allocator_destroy(server.allocator);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2482,6 +2482,10 @@ view_init(struct view *view)
|
||||||
|
|
||||||
view->title = xstrdup("");
|
view->title = xstrdup("");
|
||||||
view->app_id = xstrdup("");
|
view->app_id = xstrdup("");
|
||||||
|
|
||||||
|
view->capture.scene = wlr_scene_create();
|
||||||
|
view->capture.scene->restack_xwayland_surfaces = false;
|
||||||
|
wl_list_init(&view->capture.on_capture_source_destroy.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2503,6 +2507,9 @@ view_destroy(struct view *view)
|
||||||
wl_list_remove(&view->request_fullscreen.link);
|
wl_list_remove(&view->request_fullscreen.link);
|
||||||
wl_list_remove(&view->set_title.link);
|
wl_list_remove(&view->set_title.link);
|
||||||
wl_list_remove(&view->destroy.link);
|
wl_list_remove(&view->destroy.link);
|
||||||
|
wl_list_remove(&view->capture.on_capture_source_destroy.link);
|
||||||
|
|
||||||
|
wlr_scene_node_destroy(&view->capture.scene->tree.node);
|
||||||
|
|
||||||
if (view->foreign_toplevel) {
|
if (view->foreign_toplevel) {
|
||||||
foreign_toplevel_destroy(view->foreign_toplevel);
|
foreign_toplevel_destroy(view->foreign_toplevel);
|
||||||
|
|
|
||||||
|
|
@ -166,4 +166,6 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
|
||||||
|
|
||||||
node_descriptor_create(wlr_popup->base->surface->data,
|
node_descriptor_create(wlr_popup->base->surface->data,
|
||||||
LAB_NODE_XDG_POPUP, view, /*data*/ NULL);
|
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
|
|
@ -30,6 +30,8 @@
|
||||||
#define LAB_XDG_SHELL_VERSION 6
|
#define LAB_XDG_SHELL_VERSION 6
|
||||||
#define CONFIGURE_TIMEOUT_MS 100
|
#define CONFIGURE_TIMEOUT_MS 100
|
||||||
|
|
||||||
|
static struct view *xdg_toplevel_view_get_root(struct view *view);
|
||||||
|
|
||||||
static struct xdg_toplevel_view *
|
static struct xdg_toplevel_view *
|
||||||
xdg_toplevel_view_from_view(struct view *view)
|
xdg_toplevel_view_from_view(struct view *view)
|
||||||
{
|
{
|
||||||
|
|
@ -463,6 +465,7 @@ handle_destroy(struct wl_listener *listener, void *data)
|
||||||
/* Remove xdg-shell view specific listeners */
|
/* Remove xdg-shell view specific listeners */
|
||||||
wl_list_remove(&xdg_toplevel_view->set_app_id.link);
|
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->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(&xdg_toplevel_view->new_popup.link);
|
||||||
wl_list_remove(&view->commit.link);
|
wl_list_remove(&view->commit.link);
|
||||||
|
|
||||||
|
|
@ -566,6 +569,23 @@ handle_request_show_window_menu(struct wl_listener *listener, void *data)
|
||||||
menu_open_root(menu, cursor->x, cursor->y);
|
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
|
static void
|
||||||
handle_set_title(struct wl_listener *listener, void *data)
|
handle_set_title(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
|
@ -1024,6 +1044,9 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
|
||||||
mappable_connect(&view->mappable, xdg_surface->surface,
|
mappable_connect(&view->mappable, xdg_surface->surface,
|
||||||
handle_map, handle_unmap);
|
handle_map, handle_unmap);
|
||||||
|
|
||||||
|
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;
|
struct wlr_xdg_toplevel *toplevel = xdg_surface->toplevel;
|
||||||
CONNECT_SIGNAL(toplevel, view, destroy);
|
CONNECT_SIGNAL(toplevel, view, destroy);
|
||||||
CONNECT_SIGNAL(toplevel, view, request_move);
|
CONNECT_SIGNAL(toplevel, view, request_move);
|
||||||
|
|
@ -1037,6 +1060,7 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
|
||||||
/* Events specific to XDG toplevel views */
|
/* Events specific to XDG toplevel views */
|
||||||
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_app_id);
|
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, request_show_window_menu);
|
||||||
|
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_parent);
|
||||||
CONNECT_SIGNAL(xdg_surface, xdg_toplevel_view, new_popup);
|
CONNECT_SIGNAL(xdg_surface, xdg_toplevel_view, new_popup);
|
||||||
|
|
||||||
wl_list_insert(&server.views, &view->link);
|
wl_list_insert(&server.views, &view->link);
|
||||||
|
|
|
||||||
|
|
@ -783,6 +783,7 @@ handle_map(struct wl_listener *listener, void *data)
|
||||||
view->content_tree = wlr_scene_subsurface_tree_create(
|
view->content_tree = wlr_scene_subsurface_tree_create(
|
||||||
view->scene_tree, view->surface);
|
view->scene_tree, view->surface);
|
||||||
die_if_null(view->content_tree);
|
die_if_null(view->content_tree);
|
||||||
|
wlr_scene_subsurface_tree_create(&view->capture.scene->tree, view->surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&view->content_tree->node, !view->shaded);
|
wlr_scene_node_set_enabled(&view->content_tree->node, !view->shaded);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue