From b535e4805725eda92e86d48089457221fa8371fc Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 30 Jun 2020 00:01:02 +0200 Subject: [PATCH] wayland: Update to xdg-decoration protocol Currently gtk uses the out of date and non-standardized server-decoration protocol from kde. This commit replaces the implementation of this old server-decoration protocol with an implementation of the xdg-decoration protocol standardized in the wayland-protocols repository. Notable changes include: - New private GDK API to communicate decoration state changes to GTK - Deprecation of gdk_wayland_display_prefers_ssd(). The new protocol doesn't provide global state, so this function is deprecated and always returns false. - Renaming of gdk_wayland_window_announce_ssd() to gdk_wayland_window_request_ssd(). The server is not required to honor requests for ssd. It is however required to honor CSD if the xdg-decoration protocol object is destroyed. so gdk_wayland_window_announce_csd() is still an accurate name. --- gdk/gdk-private.c | 3 + gdk/gdk-private.h | 17 +++ gdk/wayland/Makefile.am | 5 +- gdk/wayland/gdkdisplay-wayland.c | 38 ++--- gdk/wayland/gdkdisplay-wayland.h | 6 +- gdk/wayland/gdkwaylanddisplay.h | 2 +- gdk/wayland/gdkwaylandwindow.h | 5 +- gdk/wayland/gdkwindow-wayland.c | 160 ++++++++++++++------- gdk/wayland/meson.build | 2 +- gdk/wayland/protocol/server-decoration.xml | 94 ------------ gtk/gtkwindow.c | 96 +++++++++++-- 11 files changed, 229 insertions(+), 199 deletions(-) delete mode 100644 gdk/wayland/protocol/server-decoration.xml diff --git a/gdk/gdk-private.c b/gdk/gdk-private.c index 750edcd374a..a53950460b9 100644 --- a/gdk/gdk-private.c +++ b/gdk/gdk-private.c @@ -14,6 +14,9 @@ gdk__private__ (void) gdk_gl_set_flags, gdk_window_freeze_toplevel_updates, gdk_window_thaw_toplevel_updates, +#ifdef GDK_WINDOWING_WAYLAND + gdk_wayland_window_set_decoration_listener, +#endif gdk_display_get_rendering_mode, gdk_display_set_rendering_mode, gdk_display_get_debug_updates, diff --git a/gdk/gdk-private.h b/gdk/gdk-private.h index c71abe46343..d7c5250dd87 100644 --- a/gdk/gdk-private.h +++ b/gdk/gdk-private.h @@ -23,6 +23,17 @@ void gdk_gl_set_flags (GdkGLFlags flags); void gdk_window_freeze_toplevel_updates (GdkWindow *window); void gdk_window_thaw_toplevel_updates (GdkWindow *window); +#ifdef GDK_WINDOWING_WAYLAND +typedef void (* GdkWindowDecorationNotify) (GdkWindow *window, + gboolean ssd, + void *user_data); + +void gdk_wayland_window_set_decoration_listener (GdkWindow *window, + GdkWindowDecorationNotify callback, + void *user_data); +#endif + + GdkRenderingMode gdk_display_get_rendering_mode (GdkDisplay *display); void gdk_display_set_rendering_mode (GdkDisplay *display, GdkRenderingMode mode); @@ -52,6 +63,12 @@ typedef struct { void (* gdk_window_freeze_toplevel_updates) (GdkWindow *window); void (* gdk_window_thaw_toplevel_updates) (GdkWindow *window); +#ifdef GDK_WINDOWING_WAYLAND + void (* gdk_wayland_window_set_decoration_listener) (GdkWindow *window, + GdkWindowDecorationNotify callback, + void *user_data); +#endif + GdkRenderingMode (* gdk_display_get_rendering_mode) (GdkDisplay *display); void (* gdk_display_set_rendering_mode) (GdkDisplay *display, GdkRenderingMode mode); diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am index 6595013d3f0..878b50e5455 100644 --- a/gdk/wayland/Makefile.am +++ b/gdk/wayland/Makefile.am @@ -37,8 +37,8 @@ BUILT_SOURCES = \ xdg-output-unstable-v1-client-protocol.h \ keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h \ keyboard-shortcuts-inhibit-unstable-v1-protocol.c \ - server-decoration-client-protocol.h \ - server-decoration-protocol.c \ + xdg-decoration-unstable-v1-client-protocol.h \ + xdg-decoration-unstable-v1-protocol.c \ gtk-shell-client-protocol.h \ gtk-shell-protocol.c \ primary-selection-unstable-v1-client-protocol.h \ @@ -109,7 +109,6 @@ endef EXTRA_DIST += \ protocol/gtk-primary-selection.xml \ protocol/gtk-shell.xml \ - protocol/server-decoration.xml \ meson.build -include $(top_srcdir)/git.mk diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index dee7632c3a1..f0cd6f1248b 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -47,7 +47,7 @@ #include "tablet-unstable-v2-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-foreign-unstable-v1-client-protocol.h" -#include "server-decoration-client-protocol.h" +#include "xdg-decoration-unstable-v1-client-protocol.h" /** * SECTION:wayland_interaction @@ -354,32 +354,13 @@ static const struct wl_shm_listener wl_shm_listener = { wl_shm_format }; -static void -server_decoration_manager_default_mode (void *data, - struct org_kde_kwin_server_decoration_manager *manager, - uint32_t mode) -{ - g_assert (mode <= ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER); - const char *modes[] = { - [ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE] = "none", - [ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT] = "client", - [ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER] = "server", - }; - GdkWaylandDisplay *display_wayland = data; - g_debug ("Compositor prefers decoration mode '%s'", modes[mode]); - display_wayland->server_decoration_mode = mode; -} - -static const struct org_kde_kwin_server_decoration_manager_listener server_decoration_listener = { - .default_mode = server_decoration_manager_default_mode -}; - gboolean gdk_wayland_display_prefers_ssd (GdkDisplay *display) { - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); - if (display_wayland->server_decoration_manager) - return display_wayland->server_decoration_mode == ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER; + /* If the server doesn't implement xdg-decoration, we will just client-side + * decorate. If the server does implement xdg-decoration, we will initially + * client-side decorate and possibly negotiate a change to server-side + * decorations. This function is deprecated as it is no longer useful. */ return FALSE; } @@ -503,14 +484,11 @@ gdk_registry_handle_global (void *data, wl_registry_bind (display_wayland->wl_registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1); } - else if (strcmp (interface, "org_kde_kwin_server_decoration_manager") == 0) + else if (strcmp (interface, "zxdg_decoration_manager_v1") == 0) { - display_wayland->server_decoration_manager = + display_wayland->xdg_decoration_manager = wl_registry_bind (display_wayland->wl_registry, id, - &org_kde_kwin_server_decoration_manager_interface, 1); - org_kde_kwin_server_decoration_manager_add_listener (display_wayland->server_decoration_manager, - &server_decoration_listener, - display_wayland); + &zxdg_decoration_manager_v1_interface, 1); } else if (strcmp(interface, "zxdg_output_manager_v1") == 0) { diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 62696300d15..2f4381de80b 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -95,7 +95,7 @@ struct _GdkWaylandDisplay struct zxdg_exporter_v1 *xdg_exporter; struct zxdg_importer_v1 *xdg_importer; struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; - struct org_kde_kwin_server_decoration_manager *server_decoration_manager; + struct zxdg_decoration_manager_v1 *xdg_decoration_manager; struct zxdg_output_manager_v1 *xdg_output_manager; uint32_t xdg_output_version; @@ -126,8 +126,6 @@ struct _GdkWaylandDisplay int gtk_shell_version; int xdg_output_manager_version; - uint32_t server_decoration_mode; - struct xkb_context *xkb_context; GdkWaylandSelection *selection; diff --git a/gdk/wayland/gdkwaylanddisplay.h b/gdk/wayland/gdkwaylanddisplay.h index af9cc896be0..d7f40e87572 100644 --- a/gdk/wayland/gdkwaylanddisplay.h +++ b/gdk/wayland/gdkwaylanddisplay.h @@ -57,7 +57,7 @@ GDK_AVAILABLE_IN_3_22 void gdk_wayland_display_set_startup_notification_id (GdkDisplay *display, const char *startup_id); -GDK_AVAILABLE_IN_3_22 +GDK_DEPRECATED_IN_3_24 gboolean gdk_wayland_display_prefers_ssd (GdkDisplay *display); GDK_AVAILABLE_IN_3_22 diff --git a/gdk/wayland/gdkwaylandwindow.h b/gdk/wayland/gdkwaylandwindow.h index b8a8a022435..6a9b37881ba 100644 --- a/gdk/wayland/gdkwaylandwindow.h +++ b/gdk/wayland/gdkwaylandwindow.h @@ -84,9 +84,12 @@ void gdk_wayland_window_set_application_id (GdkWindow *windo GDK_AVAILABLE_IN_3_22 void gdk_wayland_window_announce_csd (GdkWindow *window); -GDK_AVAILABLE_IN_3_24 +GDK_DEPRECATED_IN_3_24_FOR(gdk_wayland_window_request_ssd) void gdk_wayland_window_announce_ssd (GdkWindow *window); +GDK_AVAILABLE_IN_3_24 +void gdk_wayland_window_request_ssd (GdkWindow *window); + GDK_AVAILABLE_IN_3_24 void gdk_wayland_window_add_frame_callback_surface (GdkWindow *window, struct wl_surface *surface); diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index 2d7c42bd7aa..44b9440c191 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -28,6 +28,7 @@ #include "gdkdisplay-wayland.h" #include "gdkglcontext-wayland.h" #include "gdkframeclockprivate.h" +#include "gdk-private.h" #include "gdkprivate-wayland.h" #include "gdkprofilerprivate.h" #include "gdkinternals.h" @@ -123,6 +124,7 @@ struct _GdkWindowImplWayland struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; struct xdg_popup *xdg_popup; + struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; /* Legacy xdg-shell unstable v6 fallback support */ struct zxdg_surface_v6 *zxdg_surface_v6; @@ -134,7 +136,6 @@ struct _GdkWindowImplWayland struct wl_egl_window *egl_window; struct wl_egl_window *dummy_egl_window; struct zxdg_exported_v1 *xdg_exported; - struct org_kde_kwin_server_decoration *server_decoration; } display_server; EGLSurface egl_surface; @@ -239,6 +240,12 @@ struct _GdkWindowImplWayland struct wl_callback *surface_callback; GHashTable *frame_callback_surfaces; + + struct { + gboolean ssd; + GdkWindowDecorationNotify callback; + void *user_data; + } decoration_listener; }; struct _GdkWindowImplWaylandClass @@ -274,7 +281,6 @@ static void calculate_moved_to_rect_result (GdkWindow *window, static gboolean gdk_wayland_window_is_exported (GdkWindow *window); static void gdk_wayland_window_unexport (GdkWindow *window); -static void gdk_wayland_window_announce_decoration_mode (GdkWindow *window); static gboolean should_map_as_subsurface (GdkWindow *window); static gboolean should_map_as_popup (GdkWindow *window); @@ -1877,6 +1883,68 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { xdg_toplevel_close, }; +static void +call_decoration_listener_callback (GdkWindow *window) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + if (impl->decoration_listener.callback) + impl->decoration_listener.callback (window, + impl->decoration_listener.ssd, + impl->decoration_listener.user_data); +} + +static void +xdg_toplevel_decoration_configure (void *data, + struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, + uint32_t mode) +{ + GdkWindow *window = GDK_WINDOW (data); + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) + { + if (!impl->decoration_listener.ssd) + { + impl->decoration_listener.ssd = TRUE; + call_decoration_listener_callback (window); + } + } + else if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE) + { + if (impl->decoration_listener.ssd) + { + impl->decoration_listener.ssd = FALSE; + call_decoration_listener_callback (window); + } + } + else + g_assert_not_reached (); +} + +static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = { + xdg_toplevel_decoration_configure, +}; + +static void +create_xdg_toplevel_decoration (GdkWindow *window) +{ + GdkWaylandDisplay *display_wayland = + GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + if (display_wayland->xdg_decoration_manager) + { + impl->display_server.xdg_toplevel_decoration = + zxdg_decoration_manager_v1_get_toplevel_decoration (display_wayland->xdg_decoration_manager, + impl->display_server.xdg_toplevel); + zxdg_toplevel_decoration_v1_add_listener (impl->display_server.xdg_toplevel_decoration, + &xdg_toplevel_decoration_listener, + window); + zxdg_toplevel_decoration_v1_unset_mode (impl->display_server.xdg_toplevel_decoration); + } +} + static void create_xdg_toplevel_resources (GdkWindow *window) { @@ -1896,6 +1964,8 @@ create_xdg_toplevel_resources (GdkWindow *window) xdg_toplevel_add_listener (impl->display_server.xdg_toplevel, &xdg_toplevel_listener, window); + + create_xdg_toplevel_decoration(window); } static void @@ -2299,68 +2369,58 @@ window_anchor_to_gravity_legacy (GdkGravity rect_anchor) } } -static void -kwin_server_decoration_mode_set (void *data, struct org_kde_kwin_server_decoration *org_kde_kwin_server_decoration, uint32_t mode) +void +gdk_wayland_window_request_ssd (GdkWindow *window) { - GdkWindow *window = GDK_WINDOW (data); GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - if ((mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER && impl->using_csd) || - (mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT && !impl->using_csd)) - gdk_wayland_window_announce_decoration_mode (window); -} + /* This may have been destroyed in gdk_wayland_window_announce_csd() + * so create it again if needed. */ + if (!impl->display_server.xdg_toplevel_decoration) + create_xdg_toplevel_decoration(window); -static const struct org_kde_kwin_server_decoration_listener kwin_server_decoration_listener = { - kwin_server_decoration_mode_set -}; + if (impl->display_server.xdg_toplevel_decoration) + zxdg_toplevel_decoration_v1_set_mode (impl->display_server.xdg_toplevel_decoration, + ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); +} -static void -gdk_wayland_window_announce_decoration_mode (GdkWindow *window) +void +gdk_wayland_window_announce_csd (GdkWindow *window) { - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - if (!display_wayland->server_decoration_manager) - return; - if (!impl->display_server.server_decoration) + if (impl->display_server.xdg_toplevel_decoration) { - impl->display_server.server_decoration = - org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager, - impl->display_server.wl_surface); - org_kde_kwin_server_decoration_add_listener (impl->display_server.server_decoration, - &kwin_server_decoration_listener, - window); - } + zxdg_toplevel_decoration_v1_destroy(impl->display_server.xdg_toplevel_decoration); + impl->display_server.xdg_toplevel_decoration = NULL; + } - if (impl->display_server.server_decoration) + if (impl->decoration_listener.ssd) { - if (impl->using_csd) - org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration, - ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT); - else - org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration, - ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER); + impl->decoration_listener.ssd = FALSE; + call_decoration_listener_callback(window); } } void -gdk_wayland_window_announce_csd (GdkWindow *window) +gdk_wayland_window_announce_ssd (GdkWindow *window) { - GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - - impl->using_csd = TRUE; - if (impl->mapped) - gdk_wayland_window_announce_decoration_mode (window); + /* deprecated as this no is no longer an annoncement but a request */ + gdk_wayland_window_request_ssd (window); } -void -gdk_wayland_window_announce_ssd (GdkWindow *window) +void gdk_wayland_window_set_decoration_listener (GdkWindow *window, + GdkWindowDecorationNotify callback, + void *user_data) { GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - impl->using_csd = FALSE; - if (impl->mapped) - gdk_wayland_window_announce_decoration_mode (window); + /* Don't support changing the callback once set. This is a private API + * and such complexity is not currently needed. */ + g_assert(impl->decoration_listener.callback == NULL); + + impl->decoration_listener.callback = callback; + impl->decoration_listener.user_data = user_data; } static GdkWindow * @@ -3213,13 +3273,11 @@ gdk_wayland_window_map (GdkWindow *window) else { gdk_wayland_window_create_xdg_toplevel (window); - gdk_wayland_window_announce_decoration_mode (window); } } else { gdk_wayland_window_create_xdg_toplevel (window); - gdk_wayland_window_announce_decoration_mode (window); } impl->mapped = TRUE; @@ -3321,6 +3379,12 @@ gdk_wayland_window_hide_surface (GdkWindow *window) if (impl->display_server.xdg_toplevel) { + if (impl->display_server.xdg_toplevel_decoration) + { + zxdg_toplevel_decoration_v1_destroy (impl->display_server.xdg_toplevel_decoration); + impl->display_server.xdg_toplevel_decoration = NULL; + } + xdg_toplevel_destroy (impl->display_server.xdg_toplevel); impl->display_server.xdg_toplevel = NULL; } @@ -3387,12 +3451,6 @@ gdk_wayland_window_hide_surface (GdkWindow *window) impl->application.was_set = FALSE; } - if (impl->display_server.server_decoration) - { - org_kde_kwin_server_decoration_release (impl->display_server.server_decoration); - impl->display_server.server_decoration = NULL; - } - wl_surface_destroy (impl->display_server.wl_surface); impl->display_server.wl_surface = NULL; impl->surface_callback = NULL; diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index e66afd7f95b..e4906d36417 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -54,7 +54,7 @@ proto_sources = [ ['xdg-foreign', 'unstable', 'v1', ], ['tablet', 'unstable', 'v2', ], ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ], - ['server-decoration', 'private' ], + ['xdg-decoration', 'unstable', 'v1', ], ['xdg-output', 'unstable', 'v1', ], ['primary-selection', 'unstable', 'v1', ], ] diff --git a/gdk/wayland/protocol/server-decoration.xml b/gdk/wayland/protocol/server-decoration.xml deleted file mode 100644 index 8bc106c7c42..00000000000 --- a/gdk/wayland/protocol/server-decoration.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - . - ]]> - - - This interface allows to coordinate whether the server should create - a server-side window decoration around a wl_surface representing a - shell surface (wl_shell_surface or similar). By announcing support - for this interface the server indicates that it supports server - side decorations. - - - - When a client creates a server-side decoration object it indicates - that it supports the protocol. The client is supposed to tell the - server whether it wants server-side decorations or will provide - client-side decorations. - - If the client does not create a server-side decoration object for - a surface the server interprets this as lack of support for this - protocol and considers it as client-side decorated. Nevertheless a - client-side decorated surface should use this protocol to indicate - to the server that it does not want a server-side deco. - - - - - - - - - - - - - This event is emitted directly after binding the interface. It contains - the default mode for the decoration. When a new server decoration object - is created this new object will be in the default mode until the first - request_mode is requested. - - The server may change the default mode at any time. - - - - - - - - - - - - - - - - - - - - - This event is emitted directly after the decoration is created and - represents the base decoration policy by the server. E.g. a server - which wants all surfaces to be client-side decorated will send Client, - a server which wants server-side decoration will send Server. - - The client can request a different mode through the decoration request. - The server will acknowledge this by another event with the same mode. So - even if a server prefers server-side decoration it's possible to force a - client-side decoration. - - The server may emit this event at any time. In this case the client can - again request a different mode. It's the responsibility of the server to - prevent a feedback loop. - - - - - diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index d9c456e3042..4bf49580eb2 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -4166,6 +4166,19 @@ gtk_window_enable_csd (GtkWindow *window) priv->client_decorated = TRUE; } +static void +gtk_window_disable_csd (GtkWindow *window) +{ + GtkWindowPrivate *priv = window->priv; + GtkWidget *widget = GTK_WIDGET (window); + + /* Only one of these will actually be set, but removing both is harmless */ + gtk_style_context_remove_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_CSD); + gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "solid-csd"); + + priv->client_decorated = FALSE; +} + static void on_titlebar_title_notify (GtkHeaderBar *titlebar, GParamSpec *pspec, @@ -6119,10 +6132,7 @@ gtk_window_should_use_csd (GtkWindow *window) #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (window)))) - { - GdkDisplay *gdk_display = gtk_widget_get_display (GTK_WIDGET (window)); - return !gdk_wayland_display_prefers_ssd (gdk_display); - } + return TRUE; #endif #ifdef GDK_WINDOWING_WIN32 @@ -6156,6 +6166,31 @@ create_decoration (GtkWidget *widget) gtk_widget_show_all (priv->titlebar); priv->title_box = priv->titlebar; } + else if (priv->title_box == priv->titlebar) + gtk_widget_show_all (priv->title_box); + + update_window_buttons (window); +} + +static void update_shadow_width (GtkWindow *window, GtkBorder *border); + +static void +destroy_decoration (GtkWidget *widget) +{ + GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; + GtkBorder border = {0}; + + priv->use_client_shadow = FALSE; + update_shadow_width(window, &border); + + gtk_window_disable_csd (window); + + if (priv->type == GTK_WINDOW_POPUP) + return; + + if (priv->title_box == priv->titlebar) + gtk_widget_hide (priv->title_box); update_window_buttons (window); } @@ -7347,6 +7382,42 @@ update_realized_window_properties (GtkWindow *window, update_border_windows (window); } +static void +handle_decoration_state_change (GtkWidget *widget) +{ + GtkAllocation allocation; + GdkWindow *window = gtk_widget_get_window (widget); + + allocation.x = 0; + allocation.y = 0; + allocation.width = gdk_window_get_width (window); + allocation.height = gdk_window_get_height (window); + + gtk_widget_size_allocate (widget, &allocation); + gtk_widget_queue_resize (widget); +} + +static void +wayland_handle_decoration (GdkWindow *gdk_window, + gboolean ssd, + void *user_data) +{ + GtkWidget *widget = user_data; + GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; + + if (priv->client_decorated && ssd) + { + destroy_decoration(widget); + handle_decoration_state_change(widget); + } + else if (!priv->client_decorated && !ssd) + { + create_decoration(widget); + handle_decoration_state_change(widget); + } +} + static void gtk_window_realize (GtkWidget *widget) { @@ -7544,16 +7615,6 @@ gtk_window_realize (GtkWidget *widget) if (!priv->decorated || priv->client_decorated) gdk_window_set_decorations (gdk_window, 0); -#ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_WINDOW (gdk_window)) - { - if (priv->client_decorated) - gdk_wayland_window_announce_csd (gdk_window); - else - gdk_wayland_window_announce_ssd (gdk_window); - } -#endif - if (!priv->deletable) gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE); @@ -7600,6 +7661,13 @@ gtk_window_realize (GtkWidget *widget) } #endif +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) + GDK_PRIVATE_CALL (gdk_wayland_window_set_decoration_listener) (gdk_window, + wayland_handle_decoration, + widget); +#endif + child_allocation.x = 0; child_allocation.y = 0; child_allocation.width = allocation.width; -- GitLab