SDL: wayland: bind xdg-decoration-manager-v1 at protocol version 2

From edafd519b941560dd5d8cf5a5b31d4a7b80700fc Mon Sep 17 00:00:00 2001
From: rewine <[EMAIL REDACTED]>
Date: Wed, 15 Jul 2026 15:56:18 +0800
Subject: [PATCH] wayland: bind xdg-decoration-manager-v1 at protocol version 2

v2 removes v1's strict ordering requirement (decoration object must be created and configured before any buffer is attached), allowing xdg_toplevel_decoration to be created even after a buffer has already been attached/committed
---
 src/video/wayland/SDL_waylandvideo.c          |  2 +-
 .../xdg-decoration-unstable-v1.xml            | 44 ++++++++++++++-----
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 1c1fef5bcdbc1..f1e00cad018a0 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -1472,7 +1472,7 @@ static void handle_registry_global(void *data, struct wl_registry *registry, uin
         d->primary_selection_device_manager = wl_registry_bind(d->registry, id, &zwp_primary_selection_device_manager_v1_interface, 1);
         Wayland_DisplayInitPrimarySelectionDeviceManager(d);
     } else if (SDL_strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
-        d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);
+        d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, SDL_min(2, version));
     } else if (SDL_strcmp(interface, zwp_tablet_manager_v2_interface.name) == 0) {
         d->tablet_manager = wl_registry_bind(d->registry, id, &zwp_tablet_manager_v2_interface, 1);
         Wayland_DisplayInitTabletManager(d);
diff --git a/wayland-protocols/xdg-decoration-unstable-v1.xml b/wayland-protocols/xdg-decoration-unstable-v1.xml
index 378e8ff4bbf7c..023589ad04769 100644
--- a/wayland-protocols/xdg-decoration-unstable-v1.xml
+++ b/wayland-protocols/xdg-decoration-unstable-v1.xml
@@ -23,7 +23,7 @@
     DEALINGS IN THE SOFTWARE.
   </copyright>
 
-  <interface name="zxdg_decoration_manager_v1" version="1">
+  <interface name="zxdg_decoration_manager_v1" version="2">
     <description summary="window decoration manager">
       This interface allows a compositor to announce support for server-side
       decorations.
@@ -60,18 +60,33 @@
       <description summary="create a new toplevel decoration object">
         Create a new decoration object associated with the given toplevel.
 
-        Creating an xdg_toplevel_decoration from an xdg_toplevel which has a
-        buffer attached or committed is a client error, and any attempts by a
-        client to attach or manipulate a buffer prior to the first
-        xdg_toplevel_decoration.configure event must also be treated as
-        errors.
+        For objects of version 1, creating an xdg_toplevel_decoration from an
+        xdg_toplevel which has a buffer attached or committed is a client
+        error, and any attempts by a client to attach or manipulate a buffer
+        prior to the first xdg_toplevel_decoration.configure event must also be
+        treated as errors.
+
+        For objects of version 2 or newer, creating an xdg_toplevel_decoration
+        from an xdg_toplevel which has a buffer attached or committed is
+        allowed. The initial decoration mode of the surface if a buffer is
+        already attached depends on whether a xdg_toplevel_decoration object
+        has been associated with the surface or not prior to this request.
+
+        If an xdg_toplevel_decoration was associated with the surface, then
+        destroyed without a surface commit, the previous decoration mode is
+        retained.
+
+        If no xdg_toplevel_decoration was associated with the surface prior to
+        this request, or if a surface commit has been performed after a previous
+        xdg_toplevel_decoration object associated with the surface was
+        destroyed, the decoration mode is assumed to be client-side.
       </description>
       <arg name="id" type="new_id" interface="zxdg_toplevel_decoration_v1"/>
       <arg name="toplevel" type="object" interface="xdg_toplevel"/>
     </request>
   </interface>
 
-  <interface name="zxdg_toplevel_decoration_v1" version="1">
+  <interface name="zxdg_toplevel_decoration_v1" version="2">
     <description summary="decoration object for a toplevel surface">
       The decoration object allows the compositor to toggle server-side window
       decorations for a toplevel surface. The client can request to switch to
@@ -88,12 +103,14 @@
         summary="xdg_toplevel already has a decoration object"/>
       <entry name="orphaned" value="2"
         summary="xdg_toplevel destroyed before the decoration object"/>
+      <entry name="invalid_mode" value="3" summary="invalid mode"/>
     </enum>
 
     <request name="destroy" type="destructor">
       <description summary="destroy the decoration object">
         Switch back to a mode without any server-side decorations at the next
-        commit.
+        commit, unless a new xdg_toplevel_decoration is created for the surface
+        first.
       </description>
     </request>
 
@@ -113,7 +130,7 @@
         that the client prefers the provided decoration mode.
 
         After requesting a decoration mode, the compositor will respond by
-        emitting a xdg_surface.configure event. The client should then update
+        emitting an xdg_surface.configure event. The client should then update
         its content, drawing it without decorations if the received mode is
         server-side decorations. The client must also acknowledge the configure
         when committing the new content (see xdg_surface.ack_configure).
@@ -122,11 +139,14 @@
         different mode instead.
 
         Clients whose decoration mode depend on the xdg_toplevel state may send
-        a set_mode request in response to a xdg_surface.configure event and wait
+        a set_mode request in response to an xdg_surface.configure event and wait
         for the next xdg_surface.configure event to prevent unwanted state.
         Such clients are responsible for preventing configure loops and must
         make sure not to send multiple successive set_mode requests with the
         same decoration mode.
+
+        If an invalid mode is supplied by the client, the invalid_mode protocol
+        error is raised by the compositor.
       </description>
       <arg name="mode" type="uint" enum="mode" summary="the decoration mode"/>
     </request>
@@ -141,8 +161,8 @@
     </request>
 
     <event name="configure">
-      <description summary="suggest a surface change">
-        The configure event asks the client to change its decoration mode. The
+      <description summary="notify a decoration mode change">
+        The configure event configures the effective decoration mode. The
         configured state should not be applied immediately. Clients must send an
         ack_configure in response to this event. See xdg_surface.configure and
         xdg_surface.ack_configure for details.