From 700941dde8d270b7986bd592fcb42333e7626718 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 13 Jul 2018 21:53:56 +0100 Subject: [PATCH 1/3] Listen to server-decoration mode changes --- include/sway/decoration.h | 13 +++++++++++++ include/sway/server.h | 10 +++++++++- sway/decoration.c | 41 +++++++++++++++++++++++++++++++++++++++ sway/meson.build | 5 +++-- sway/server.c | 9 ++++++--- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 include/sway/decoration.h create mode 100644 sway/decoration.c diff --git a/include/sway/decoration.h b/include/sway/decoration.h new file mode 100644 index 00000000..c77c04c7 --- /dev/null +++ b/include/sway/decoration.h @@ -0,0 +1,13 @@ +#ifndef _SWAY_DECORATION_H +#define _SWAY_DECORATION_H + +#include + +struct sway_server_decoration { + struct wlr_server_decoration *wlr_server_decoration; + + struct wl_listener destroy; + struct wl_listener mode; +}; + +#endif diff --git a/include/sway/server.h b/include/sway/server.h index a3782f91..7e73fb4f 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -4,12 +4,13 @@ #include #include #include +#include #include #include #include +#include #include #include -#include // TODO WLR: make Xwayland optional #include "list.h" #include "config.h" @@ -42,11 +43,16 @@ struct sway_server { struct wlr_xdg_shell *xdg_shell; struct wl_listener xdg_shell_surface; + #ifdef HAVE_XWAYLAND struct sway_xwayland xwayland; struct wl_listener xwayland_surface; struct wl_listener xwayland_ready; #endif + + struct wlr_server_decoration_manager *server_decoration_manager; + struct wl_listener server_decoration; + bool debug_txn_timings; list_t *transactions; @@ -71,4 +77,6 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data); #ifdef HAVE_XWAYLAND void handle_xwayland_surface(struct wl_listener *listener, void *data); #endif +void handle_server_decoration(struct wl_listener *listener, void *data); + #endif diff --git a/sway/decoration.c b/sway/decoration.c new file mode 100644 index 00000000..73b3f45d --- /dev/null +++ b/sway/decoration.c @@ -0,0 +1,41 @@ +#include +#include "sway/decoration.h" +#include "sway/server.h" +#include "sway/tree/view.h" +#include "log.h" + +static void server_decoration_handle_destroy(struct wl_listener *listener, + void *data) { + struct sway_server_decoration *deco = + wl_container_of(listener, deco, destroy); + wl_list_remove(&deco->destroy.link); + free(deco); +} + +static void server_decoration_handle_mode(struct wl_listener *listener, + void *data) { + struct sway_server_decoration *deco = + wl_container_of(listener, deco, mode); + struct sway_view *view = + view_from_wlr_surface(deco->wlr_server_decoration->surface); + + // TODO + wlr_log(WLR_ERROR, "%p %d", view, deco->wlr_server_decoration->mode); +} + +void handle_server_decoration(struct wl_listener *listener, void *data) { + struct wlr_server_decoration *wlr_deco = data; + + struct sway_server_decoration *deco = calloc(1, sizeof(*deco)); + if (deco == NULL) { + return; + } + + deco->wlr_server_decoration = wlr_deco; + + wl_signal_add(&wlr_deco->events.destroy, &deco->destroy); + deco->destroy.notify = server_decoration_handle_destroy; + + wl_signal_add(&wlr_deco->events.mode, &deco->mode); + deco->mode.notify = server_decoration_handle_mode; +} diff --git a/sway/meson.build b/sway/meson.build index c18fb6e2..2a457270 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -1,13 +1,14 @@ sway_sources = files( - 'main.c', - 'server.c', 'commands.c', 'config.c', 'criteria.c', 'debug-tree.c', + 'decoration.c', 'ipc-json.c', 'ipc-server.c', + 'main.c', 'security.c', + 'server.c', 'swaynag.c', 'desktop/desktop.c', diff --git a/sway/server.c b/sway/server.c index e8755360..bf6255bc 100644 --- a/sway/server.c +++ b/sway/server.c @@ -109,11 +109,14 @@ bool server_init(struct sway_server *server) { } #endif - // TODO: Integration with sway borders - struct wlr_server_decoration_manager *deco_manager = + server->server_decoration_manager = wlr_server_decoration_manager_create(server->wl_display); wlr_server_decoration_manager_set_default_mode( - deco_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + server->server_decoration_manager, + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + wl_signal_add(&server->server_decoration_manager->events.new_decoration, + &server->server_decoration); + server->server_decoration.notify = handle_server_decoration; wlr_linux_dmabuf_v1_create(server->wl_display, renderer); wlr_export_dmabuf_manager_v1_create(server->wl_display); From 9d578e0a0f08e053dfc1982e32d9fda172b0087f Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 29 Jul 2018 18:31:10 +0100 Subject: [PATCH 2/3] Handle views created after decoration mode is sent for xdg-shell --- include/sway/decoration.h | 4 ++++ include/sway/server.h | 1 + include/sway/tree/view.h | 4 ++++ sway/decoration.c | 34 ++++++++++++++++++++++++++++++++-- sway/desktop/xdg_shell.c | 19 +++++++++++++++++++ sway/server.c | 3 +-- 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/include/sway/decoration.h b/include/sway/decoration.h index c77c04c7..7916746e 100644 --- a/include/sway/decoration.h +++ b/include/sway/decoration.h @@ -5,9 +5,13 @@ struct sway_server_decoration { struct wlr_server_decoration *wlr_server_decoration; + struct wl_list link; struct wl_listener destroy; struct wl_listener mode; }; +struct sway_server_decoration *decoration_from_surface( + struct wlr_surface *surface); + #endif diff --git a/include/sway/server.h b/include/sway/server.h index 7e73fb4f..b93584b6 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -52,6 +52,7 @@ struct sway_server { struct wlr_server_decoration_manager *server_decoration_manager; struct wl_listener server_decoration; + struct wl_list decorations; // sway_server_decoration::link bool debug_txn_timings; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 37fd02bc..e91d2a20 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -118,6 +118,8 @@ struct sway_view { struct sway_xdg_shell_v6_view { struct sway_view view; + enum wlr_server_decoration_manager_mode deco_mode; + struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; @@ -134,6 +136,8 @@ struct sway_xdg_shell_v6_view { struct sway_xdg_shell_view { struct sway_view view; + enum wlr_server_decoration_manager_mode deco_mode; + struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; diff --git a/sway/decoration.c b/sway/decoration.c index 73b3f45d..0e3e67ac 100644 --- a/sway/decoration.c +++ b/sway/decoration.c @@ -9,6 +9,8 @@ static void server_decoration_handle_destroy(struct wl_listener *listener, struct sway_server_decoration *deco = wl_container_of(listener, deco, destroy); wl_list_remove(&deco->destroy.link); + wl_list_remove(&deco->mode.link); + wl_list_remove(&deco->link); free(deco); } @@ -18,9 +20,24 @@ static void server_decoration_handle_mode(struct wl_listener *listener, wl_container_of(listener, deco, mode); struct sway_view *view = view_from_wlr_surface(deco->wlr_server_decoration->surface); + if (view == NULL || view->surface != deco->wlr_server_decoration->surface) { + return; + } - // TODO - wlr_log(WLR_ERROR, "%p %d", view, deco->wlr_server_decoration->mode); + switch (view->type) { + case SWAY_VIEW_XDG_SHELL_V6:; + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + (struct sway_xdg_shell_v6_view *)view; + xdg_shell_v6_view->deco_mode = deco->wlr_server_decoration->mode; + break; + case SWAY_VIEW_XDG_SHELL:; + struct sway_xdg_shell_view *xdg_shell_view = + (struct sway_xdg_shell_view *)view; + xdg_shell_view->deco_mode = deco->wlr_server_decoration->mode; + break; + default: + break; + } } void handle_server_decoration(struct wl_listener *listener, void *data) { @@ -38,4 +55,17 @@ void handle_server_decoration(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_deco->events.mode, &deco->mode); deco->mode.notify = server_decoration_handle_mode; + + wl_list_insert(&server.decorations, &deco->link); +} + +struct sway_server_decoration *decoration_from_surface( + struct wlr_surface *surface) { + struct sway_server_decoration *deco; + wl_list_for_each(deco, &server.decorations, link) { + if (deco->wlr_server_decoration->surface == surface) { + return deco; + } + } + return NULL; } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index b364663d..3b73f99c 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -6,6 +6,7 @@ #include #include #include "log.h" +#include "sway/decoration.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/server.h" @@ -170,6 +171,15 @@ static bool wants_floating(struct sway_view *view) { || toplevel->parent; } +static bool has_client_side_decorations(struct sway_view *view) { + struct sway_xdg_shell_view *xdg_shell_view = + xdg_shell_view_from_view(view); + if (xdg_shell_view == NULL) { + return true; + } + return xdg_shell_view->deco_mode != WLR_SERVER_DECORATION_MANAGER_MODE_SERVER; +} + static void for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_view_from_view(view) == NULL) { @@ -226,6 +236,7 @@ static const struct sway_view_impl view_impl = { .set_tiled = set_tiled, .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, + .has_client_side_decorations = has_client_side_decorations, .for_each_surface = for_each_surface, .for_each_popup = for_each_popup, .close = _close, @@ -357,6 +368,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_height = view->wlr_xdg_surface->surface->current.height; } + struct sway_server_decoration *deco = + decoration_from_surface(xdg_surface->surface); + if (deco != NULL) { + xdg_shell_view->deco_mode = deco->wlr_server_decoration->mode; + } else { + xdg_shell_view->deco_mode = WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; + } + view_map(view, view->wlr_xdg_surface->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { diff --git a/sway/server.c b/sway/server.c index bf6255bc..e8dc63be 100644 --- a/sway/server.c +++ b/sway/server.c @@ -19,7 +19,6 @@ #include #include #include -// TODO WLR: make Xwayland optional #include "list.h" #include "sway/config.h" #include "sway/desktop/idle_inhibit_v1.h" @@ -85,7 +84,6 @@ bool server_init(struct sway_server *server) { &server->xdg_shell_surface); server->xdg_shell_surface.notify = handle_xdg_shell_surface; - // TODO make xwayland optional #ifdef HAVE_XWAYLAND server->xwayland.wlr_xwayland = wlr_xwayland_create(server->wl_display, server->compositor, true); @@ -117,6 +115,7 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->server_decoration_manager->events.new_decoration, &server->server_decoration); server->server_decoration.notify = handle_server_decoration; + wl_list_init(&server->decorations); wlr_linux_dmabuf_v1_create(server->wl_display, renderer); wlr_export_dmabuf_manager_v1_create(server->wl_display); From d2ac48f9206e9962ab47f337f824ce7f69ffb9c1 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 6 Aug 2018 15:28:33 +0100 Subject: [PATCH 3/3] Handle views created after decoration mode is sent for xdg-shell-v6 --- sway/desktop/xdg_shell_v6.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ffea03ad..a947fb35 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -4,14 +4,15 @@ #include #include #include +#include "log.h" +#include "sway/decoration.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/server.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/tree/view.h" -#include "sway/input/seat.h" -#include "sway/input/input-manager.h" -#include "log.h" static const struct sway_view_child_impl popup_impl; @@ -166,6 +167,15 @@ static bool wants_floating(struct sway_view *view) { || toplevel->parent; } +static bool has_client_side_decorations(struct sway_view *view) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { + return true; + } + return xdg_shell_v6_view->deco_mode != WLR_SERVER_DECORATION_MANAGER_MODE_SERVER; +} + static void for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_v6_view_from_view(view) == NULL) { @@ -223,6 +233,7 @@ static const struct sway_view_impl view_impl = { .set_tiled = set_tiled, .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, + .has_client_side_decorations = has_client_side_decorations, .for_each_surface = for_each_surface, .for_each_popup = for_each_popup, .close = _close, @@ -353,6 +364,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_height = view->wlr_xdg_surface_v6->surface->current.height; } + struct sway_server_decoration *deco = + decoration_from_surface(xdg_surface->surface); + if (deco != NULL) { + xdg_shell_v6_view->deco_mode = deco->wlr_server_decoration->mode; + } else { + xdg_shell_v6_view->deco_mode = WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; + } + view_map(view, view->wlr_xdg_surface_v6->surface); if (xdg_surface->toplevel->client_pending.fullscreen) {