From 58039edf695e8bf7b0cf7aa2eea5e792ba934a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 29 Nov 2023 04:27:09 +0100 Subject: [PATCH] [gtk3/wayland] Expose XDG-shell suspended state via visibility events. This allows Wayland compositors to tell GTK applications whether a window is effectively invisible. --- gdk/wayland/gdkdisplay-wayland.c | 8 +++++++- gdk/wayland/gdkwindow-wayland.c | 31 ++++++++++++++++++++++++++++--- meson.build | 1 + 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index bd35fea4dd..7c5e2f8771 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -49,6 +49,12 @@ #include "xdg-foreign-unstable-v1-client-protocol.h" #include "server-decoration-client-protocol.h" +#ifdef HAVE_TOPLEVEL_STATE_SUSPENDED +#define XDG_WM_BASE_VERSION 6 +#else +#define XDG_WM_BASE_VERSION 2 +#endif + /** * SECTION:wayland_interaction * @Short_description: Wayland backend-specific functions @@ -653,7 +659,7 @@ _gdk_wayland_display_open (const gchar *display_name) wl_registry_bind (display_wayland->wl_registry, display_wayland->xdg_wm_base_id, &xdg_wm_base_interface, - MIN (display_wayland->xdg_wm_base_version, 2)); + MIN (display_wayland->xdg_wm_base_version, XDG_WM_BASE_VERSION)); xdg_wm_base_add_listener (display_wayland->xdg_wm_base, &xdg_wm_base_listener, display_wayland); diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index 815a28014e..2bbff80bee 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -148,6 +148,7 @@ struct _GdkWindowImplWayland unsigned int pending_commit : 1; unsigned int awaiting_frame : 1; unsigned int using_csd : 1; + unsigned int suspended : 1; GdkWindowTypeHint hint; GdkWindow *transient_for; GdkWindow *popup_parent; @@ -225,6 +226,7 @@ struct _GdkWindowImplWayland int width; int height; GdkWindowState state; + gboolean suspended; } pending; struct { @@ -290,6 +292,7 @@ _gdk_window_impl_wayland_init (GdkWindowImplWayland *impl) impl->initial_fullscreen_monitor = -1; impl->saved_width = -1; impl->saved_height = -1; + impl->suspended = FALSE; } static void @@ -1669,6 +1672,7 @@ gdk_wayland_window_handle_configure (GdkWindow *window, GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); GdkWindowState new_state; + gboolean suspended; int width = impl->pending.width; int height = impl->pending.height; gboolean fixed_size; @@ -1692,6 +1696,19 @@ gdk_wayland_window_handle_configure (GdkWindow *window, return; } + suspended = impl->pending.suspended; + impl->pending.suspended = FALSE; + + if (impl->suspended != suspended) + { + GdkEvent* event; + + impl->suspended = suspended; + + event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY, NULL, FALSE); + event->visibility.state = suspended ? GDK_VISIBILITY_FULLY_OBSCURED : GDK_VISIBILITY_UNOBSCURED; + } + new_state = impl->pending.state; impl->pending.state = 0; @@ -1806,11 +1823,13 @@ static void gdk_wayland_window_handle_configure_toplevel (GdkWindow *window, int32_t width, int32_t height, - GdkWindowState state) + GdkWindowState state, + gboolean suspended) { GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); impl->pending.state |= state; + impl->pending.suspended |= suspended; impl->pending.width = width; impl->pending.height = height; } @@ -1856,6 +1875,7 @@ xdg_toplevel_configure (void *data, GdkWindow *window = GDK_WINDOW (data); uint32_t *p; GdkWindowState pending_state = 0; + gboolean suspended = FALSE; wl_array_for_each (p, states) { @@ -1886,6 +1906,11 @@ xdg_toplevel_configure (void *data, case XDG_TOPLEVEL_STATE_TILED_LEFT: pending_state |= (GDK_WINDOW_STATE_TILED | GDK_WINDOW_STATE_LEFT_TILED); break; +#ifdef HAVE_TOPLEVEL_STATE_SUSPENDED + case XDG_TOPLEVEL_STATE_SUSPENDED: + suspended = TRUE; + break; +#endif default: /* Unknown state */ break; @@ -1893,7 +1918,7 @@ xdg_toplevel_configure (void *data, } gdk_wayland_window_handle_configure_toplevel (window, width, height, - pending_state); + pending_state, suspended); } static void @@ -1997,7 +2022,7 @@ zxdg_toplevel_v6_configure (void *data, } gdk_wayland_window_handle_configure_toplevel (window, width, height, - pending_state); + pending_state, FALSE); } static void diff --git a/meson.build b/meson.build index d3ed1afb26..51a2c09e49 100644 --- a/meson.build +++ b/meson.build @@ -542,6 +542,7 @@ if wayland_enabled backend_immodules += ['wayland'] cdata.set('HAVE_XDG_ACTIVATION', wlprotocolsdep.version().version_compare('>=1.21')) + cdata.set('HAVE_TOPLEVEL_STATE_SUSPENDED', wlprotocolsdep.version().version_compare('>=1.32')) wayland_pkgs = [ 'wayland-client', wayland_req,