diff --git a/cage.c b/cage.c index cf8c71f..8fa42c6 100644 --- a/cage.c +++ b/cage.c @@ -1,6 +1,6 @@ /* * Cage: A Wayland kiosk. - * + * * Copyright (C) 2018-2019 Jente Hidskes * * See the LICENSE file accompanying this file. @@ -27,6 +27,7 @@ #if CAGE_HAS_XWAYLAND #include #endif +#include #include #include #if CAGE_HAS_XWAYLAND @@ -84,6 +85,7 @@ usage(FILE *file, const char *cage) { fprintf(file, "Usage: %s APPLICATION\n" "\n" + " -d\t Don't draw client side decorations, when possible\n" " -D\t Turn on damage tracking debugging\n" " -h\t Display this help message\n", cage); @@ -93,8 +95,11 @@ static bool parse_args(struct cg_server *server, int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "hD")) != -1) { + while ((c = getopt(argc, argv, "dDh")) != -1) { switch (c) { + case 'd': + server->xdg_decoration = true; + break; case 'D': server->debug_damage_tracking = true; break; @@ -123,6 +128,7 @@ main(int argc, char *argv[]) struct wlr_renderer *renderer = NULL; struct wlr_compositor *compositor = NULL; struct wlr_data_device_manager *data_device_mgr = NULL; + struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL; struct wlr_xdg_shell *xdg_shell = NULL; #if CAGE_HAS_XWAYLAND struct wlr_xwayland *xwayland = NULL; @@ -160,6 +166,8 @@ main(int argc, char *argv[]) renderer = wlr_backend_get_renderer(server.backend); wlr_renderer_init_wl_display(renderer, server.wl_display); + wl_list_init(&server.views); + server.output_layout = wlr_output_layout_create(); if (!server.output_layout) { wlr_log(WLR_ERROR, "Unable to create output layout"); @@ -210,17 +218,20 @@ main(int argc, char *argv[]) server.new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1_new; wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, &server.new_idle_inhibitor_v1); wl_list_init(&server.inhibitors); - + xdg_shell = wlr_xdg_shell_create(server.wl_display); if (!xdg_shell) { wlr_log(WLR_ERROR, "Unable to create the XDG shell interface"); ret = 1; goto end; } - wl_list_init(&server.views); server.new_xdg_shell_surface.notify = handle_xdg_shell_surface_new; wl_signal_add(&xdg_shell->events.new_surface, &server.new_xdg_shell_surface); + xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(server.wl_display); + wl_signal_add(&xdg_decoration_manager->events.new_toplevel_decoration, &server.xdg_toplevel_decoration); + server.xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration; + #if CAGE_HAS_XWAYLAND xwayland = wlr_xwayland_create(server.wl_display, compositor, true); if (!xwayland) { @@ -293,6 +304,7 @@ main(int argc, char *argv[]) end: seat_destroy(server.seat); + wlr_xdg_decoration_manager_v1_destroy(xdg_decoration_manager); wlr_xdg_shell_destroy(xdg_shell); wlr_idle_inhibit_v1_destroy(server.idle_inhibit_v1); if (server.idle) { diff --git a/server.h b/server.h index 75e07fa..213fe09 100644 --- a/server.h +++ b/server.h @@ -8,6 +8,7 @@ #include #include #include +#include #if CAGE_HAS_XWAYLAND #include #endif @@ -19,8 +20,6 @@ struct cg_server { struct wl_display *wl_display; struct wlr_backend *backend; - - struct wl_listener new_xdg_shell_surface; struct wl_list views; struct cg_seat *seat; @@ -33,10 +32,13 @@ struct cg_server { struct cg_output *output; struct wl_listener new_output; + struct wl_listener xdg_toplevel_decoration; + struct wl_listener new_xdg_shell_surface; #if CAGE_HAS_XWAYLAND struct wl_listener new_xwayland_surface; #endif + bool xdg_decoration; #ifdef DEBUG bool debug_damage_tracking; #endif diff --git a/xdg_shell.c b/xdg_shell.c index 210d600..4fcb00e 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -17,6 +17,30 @@ #include "view.h" #include "xdg_shell.h" +static void +xdg_decoration_handle_destroy(struct wl_listener *listener, void *data) +{ + struct cg_xdg_decoration *xdg_decoration = wl_container_of(listener, xdg_decoration, destroy); + + wl_list_remove(&xdg_decoration->destroy.link); + wl_list_remove(&xdg_decoration->request_mode.link); + free(xdg_decoration); +} + +static void +xdg_decoration_handle_request_mode(struct wl_listener *listener, void *data) +{ + struct cg_xdg_decoration *xdg_decoration = wl_container_of(listener, xdg_decoration, request_mode); + enum wlr_xdg_toplevel_decoration_v1_mode mode; + + if (xdg_decoration->server->xdg_decoration) { + mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + } else { + mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } + wlr_xdg_toplevel_decoration_v1_set_mode(xdg_decoration->wlr_decoration, mode); +} + static void xdg_popup_destroy(struct cg_view_child *child) { @@ -304,3 +328,25 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) xdg_shell_view->new_popup.notify = handle_new_xdg_popup; wl_signal_add(&xdg_surface->events.new_popup, &xdg_shell_view->new_popup); } + +void +handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, xdg_toplevel_decoration); + struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration = data; + + struct cg_xdg_decoration *xdg_decoration = calloc(1, sizeof(struct cg_xdg_decoration)); + if (!xdg_decoration) { + return; + } + + xdg_decoration->wlr_decoration = wlr_decoration; + xdg_decoration->server = server; + + xdg_decoration->destroy.notify = xdg_decoration_handle_destroy; + wl_signal_add(&wlr_decoration->events.destroy, &xdg_decoration->destroy); + xdg_decoration->request_mode.notify = xdg_decoration_handle_request_mode; + wl_signal_add(&wlr_decoration->events.request_mode, &xdg_decoration->request_mode); + + xdg_decoration_handle_request_mode(&xdg_decoration->request_mode, wlr_decoration); +} diff --git a/xdg_shell.h b/xdg_shell.h index 0afd6f2..60ba535 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -2,6 +2,7 @@ #define CG_XDG_SHELL_H #include +#include #include #include "view.h" @@ -28,6 +29,15 @@ struct cg_xdg_popup { struct wl_listener new_popup; }; +struct cg_xdg_decoration { + struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration; + struct cg_server *server; + struct wl_listener destroy; + struct wl_listener request_mode; +}; + void handle_xdg_shell_surface_new(struct wl_listener *listener, void *data); +void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data); + #endif