From 167ed92fe4129a6d73a9bb0936f9bd97a9e2484f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 24 Aug 2023 18:20:33 +0200
Subject: [PATCH] wayland/xdg-shell: Implement support for
 xdg_toplevel.wm_capabilities

Nothing dynamic yet, we don't have API for this, but we need it to
implement the next version. Sending "all" should be equivalent to v4
anyhow, so this is harmless.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3019>
---
 src/wayland/meta-wayland-versions.h  |  2 +-
 src/wayland/meta-wayland-xdg-shell.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 3673369a5..b671fc8f5 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -37,7 +37,7 @@
 /* Global/master objects (version exported by wl_registry and negotiated through bind) */
 #define META_WL_COMPOSITOR_VERSION          5
 #define META_WL_DATA_DEVICE_MANAGER_VERSION 3
-#define META_XDG_WM_BASE_VERSION            4
+#define META_XDG_WM_BASE_VERSION            5
 #define META_WL_SEAT_VERSION                5
 #define META_WL_OUTPUT_VERSION              4
 #define META_XSERVER_VERSION                1
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index b87cb9aee..80a41cc46 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -693,11 +693,20 @@ fill_states (MetaWaylandXdgToplevel *xdg_toplevel,
     }
 }
 
+static void
+add_wm_capability_value (struct wl_array                   *states,
+                         enum xdg_toplevel_wm_capabilities  wm_capability)
+{
+  *((uint32_t *) wl_array_add (states, sizeof (uint32_t))) = wm_capability;
+}
+
 static void
 meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel         *xdg_toplevel,
                                           MetaWaylandWindowConfiguration *configuration)
 {
   MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel);
+  MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
+    meta_wayland_xdg_surface_get_instance_private (xdg_surface);
   struct wl_array states;
 
   wl_array_init (&states);
@@ -715,6 +724,25 @@ meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel         *xdg_to
                                            configuration->scale));
     }
 
+  if (!xdg_surface_priv->configure_sent &&
+      wl_resource_get_version (xdg_toplevel->resource) >=
+      XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
+    {
+      struct wl_array wm_capabilities;
+
+      wl_array_init (&wm_capabilities);
+      add_wm_capability_value (&wm_capabilities,
+                               XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU);
+      add_wm_capability_value (&wm_capabilities,
+                               XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE);
+      add_wm_capability_value (&wm_capabilities,
+                               XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
+      add_wm_capability_value (&wm_capabilities,
+                               XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE);
+      xdg_toplevel_send_wm_capabilities (xdg_toplevel->resource, &wm_capabilities);
+      wl_array_release (&wm_capabilities);
+    }
+
   xdg_toplevel_send_configure (xdg_toplevel->resource,
                                configuration->width / configuration->scale,
                                configuration->height / configuration->scale,
