SDL: wayland: Add support for wl_fixes.ack_global_remove

From 6eba2f2efeb24326b1583a3ca8303f3d4f7c30c6 Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <[EMAIL REDACTED]>
Date: Fri, 13 Mar 2026 22:29:22 +0200
Subject: [PATCH] wayland: Add support for wl_fixes.ack_global_remove

The wl_fixes.ack_global_remove request signals the compositor that the
client will not bind the removed global. It can be used by the
compositor to decide when it is safe to actually destroy the
corresponding global. If a global is destroyed too soon, some clients may
get disconnected.

See also https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/533
---
 src/video/wayland/SDL_waylandvideo.c |   22 +-
 wayland-protocols/wayland.xml        | 3181 ++++++++++++++------------
 2 files changed, 1678 insertions(+), 1525 deletions(-)

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index f1e00cad018a0..6abe2ff2380e1 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -112,7 +112,9 @@
 #define SDL_WL_DATA_DEVICE_VERSION 3
 
 // wl_fixes was introduced in 1.24.0
-#if SDL_WAYLAND_CHECK_VERSION(1, 24, 0)
+#if SDL_WAYLAND_CHECK_VERSION(1, 26, 0)
+#define SDL_WL_FIXES_VERSION 2
+#elif SDL_WAYLAND_CHECK_VERSION(1, 24, 0)
 #define SDL_WL_FIXES_VERSION 1
 #endif
 
@@ -561,7 +563,11 @@ static void wayland_preferred_check_handle_global(void *data, struct wl_registry
 
 static void wayland_preferred_check_remove_global(void *data, struct wl_registry *registry, uint32_t id)
 {
-    // No need to do anything here.
+    SDL_WaylandPreferredData *d = (SDL_WaylandPreferredData *)data;
+
+    if (d->wl_fixes && wl_fixes_get_version(d->wl_fixes) >= WL_FIXES_ACK_GLOBAL_REMOVE_SINCE_VERSION) {
+        wl_fixes_ack_global_remove(d->wl_fixes, registry, id);
+    }
 }
 
 static const struct wl_registry_listener preferred_registry_listener = {
@@ -1537,18 +1543,22 @@ static void handle_registry_remove_global(void *data, struct wl_registry *regist
             }
 
             d->output_count--;
-            return;
+            goto ack_remove;
         }
     }
 
     SDL_WaylandSeat *seat, *temp;
-    wl_list_for_each_safe (seat, temp, &d->seat_list, link)
-    {
+    wl_list_for_each_safe (seat, temp, &d->seat_list, link) {
         if (seat->registry_id == id) {
             Wayland_SeatDestroy(seat, false);
-            return;
+            goto ack_remove;
         }
     }
+
+ack_remove:
+    if (d->wl_fixes && wl_fixes_get_version(d->wl_fixes) >= WL_FIXES_ACK_GLOBAL_REMOVE_SINCE_VERSION) {
+        wl_fixes_ack_global_remove(d->wl_fixes, registry, id);
+    }
 }
 
 static const struct wl_registry_listener registry_listener = {
diff --git a/wayland-protocols/wayland.xml b/wayland-protocols/wayland.xml
index bee74a1008475..28babc70d9369 100644
--- a/wayland-protocols/wayland.xml
+++ b/wayland-protocols/wayland.xml
@@ -36,47 +36,47 @@
 
     <request name="sync">
       <description summary="asynchronous roundtrip">
-	The sync request asks the server to emit the 'done' event
-	on the returned wl_callback object.  Since requests are
-	handled in-order and events are delivered in-order, this can
-	be used as a barrier to ensure all previous requests and the
-	resulting events have been handled.
+        The sync request asks the server to emit the 'done' event
+        on the returned wl_callback object.  Since requests are
+        handled in-order and events are delivered in-order, this can
+        be used as a barrier to ensure all previous requests and the
+        resulting events have been handled.
 
-	The object returned by this request will be destroyed by the
-	compositor after the callback is fired and as such the client must not
-	attempt to use it after that point.
+        The object returned by this request will be destroyed by the
+        compositor after the callback is fired and as such the client must not
+        attempt to use it after that point.
 
-	The callback_data passed in the callback is undefined and should be ignored.
+        The callback_data passed in the callback is undefined and should be ignored.
       </description>
       <arg name="callback" type="new_id" interface="wl_callback"
-	   summary="callback object for the sync request"/>
+           summary="callback object for the sync request"/>
     </request>
 
     <request name="get_registry">
       <description summary="get global registry object">
-	This request creates a registry object that allows the client
-	to list and bind the global objects available from the
-	compositor.
+        This request creates a registry object that allows the client
+        to list and bind the global objects available from the
+        compositor.
 
-	It should be noted that the server side resources consumed in
-	response to a get_registry request can only be released when the
-	client disconnects, not when the client side proxy is destroyed.
-	Therefore, clients should invoke get_registry as infrequently as
-	possible to avoid wasting memory.
+        It should be noted that the server side resources consumed in
+        response to a get_registry request can only be released when the
+        client disconnects, not when the client side proxy is destroyed.
+        Therefore, clients should invoke get_registry as infrequently as
+        possible to avoid wasting memory.
       </description>
       <arg name="registry" type="new_id" interface="wl_registry"
-	   summary="global registry object"/>
+           summary="global registry object"/>
     </request>
 
     <event name="error">
       <description summary="fatal error event">
-	The error event is sent out when a fatal (non-recoverable)
-	error has occurred.  The object_id argument is the object
-	where the error occurred, most often in response to a request
-	to that object.  The code identifies the error and is defined
-	by the object interface.  As such, each interface defines its
-	own set of error codes.  The message is a brief description
-	of the error, for (debugging) convenience.
+        The error event is sent out when a fatal (non-recoverable)
+        error has occurred.  The object_id argument is the object
+        where the error occurred, most often in response to a request
+        to that object.  The code identifies the error and is defined
+        by the object interface.  As such, each interface defines its
+        own set of error codes.  The message is a brief description
+        of the error, for (debugging) convenience.
       </description>
       <arg name="object_id" type="object" summary="object where the error occurred"/>
       <arg name="code" type="uint" summary="error code"/>
@@ -85,26 +85,30 @@
 
     <enum name="error">
       <description summary="global error values">
-	These errors are global and can be emitted in response to any
-	server request.
+        These errors are global and can be emitted in response to any
+        server request.
       </description>
       <entry name="invalid_object" value="0"
-	     summary="server couldn't find object"/>
+             summary="server couldn't find object"/>
       <entry name="invalid_method" value="1"
-	     summary="method doesn't exist on the specified interface or malformed request"/>
+             summary="method doesn't exist on the specified interface or malformed request"/>
       <entry name="no_memory" value="2"
-	     summary="server is out of memory"/>
+             summary="server is out of memory"/>
       <entry name="implementation" value="3"
-	     summary="implementation error in compositor"/>
+             summary="implementation error in compositor"/>
     </enum>
 
     <event name="delete_id">
       <description summary="acknowledge object ID deletion">
-	This event is used internally by the object ID management
-	logic. When a client deletes an object that it had created,
-	the server will send this event to acknowledge that it has
-	seen the delete request. When the client receives this event,
-	it will know that it can safely reuse the object ID.
+        This event is used internally by the object ID management logic.
+
+        When the server stops using an object created by the client, the server
+        sends this event. In particular, after sending this event, the server
+        will no longer send any events that contain the object as the receiver
+        or as an argument.
+
+        When the client receives this event, it knows that it can reuse the
+        object ID.
       </description>
       <arg name="id" type="uint" summary="deleted object ID"/>
     </event>
@@ -136,20 +140,20 @@
 
     <request name="bind">
       <description summary="bind an object to the display">
-	Binds a new, client-created object to the server using the
-	specified name as the identifier.
+        Binds a new, client-created object to the server using the
+        specified name as the identifier.
       </description>
       <arg name="name" type="uint" summary="unique numeric name of the object"/>
-      <arg name="id" type="new_id" summary="bounded object"/>
+      <arg name="id" type="new_id" summary="bound object"/>
     </request>
 
     <event name="global">
       <description summary="announce global object">
-	Notify the client of global objects.
+        Notify the client of global objects.
 
-	The event notifies the client that a global object with
-	the given name is now available, and it implements the
-	given version of the given interface.
+        The event notifies the client that a global object with
+        the given name is now available, and it implements the
+        given version of the given interface.
       </description>
       <arg name="name" type="uint" summary="numeric name of the global object"/>
       <arg name="interface" type="string" summary="interface implemented by the object"/>
@@ -158,22 +162,22 @@
 
     <event name="global_remove">
       <description summary="announce removal of global object">
-	Notify the client of removed global objects.
+        Notify the client of removed global objects.
 
-	This event notifies the client that the global identified
-	by name is no longer available.  If the client bound to
-	the global using the bind request, the client should now
-	destroy that object.
+        This event notifies the client that the global identified
+        by name is no longer available.  If the client bound to
+        the global using the bind request, the client should now
+        destroy that object.
 
-	The object remains valid and requests to the object will be
-	ignored until the client destroys it, to avoid races between
-	the global going away and a client sending a request to it.
+        The object remains valid and requests to the object will be
+        ignored until the client destroys it, to avoid races between
+        the global going away and a client sending a request to it.
       </description>
       <arg name="name" type="uint" summary="numeric name of the global object"/>
     </event>
   </interface>
 
-  <interface name="wl_callback" version="1">
+  <interface name="wl_callback" version="1" frozen="true">
     <description summary="callback object">
       Clients can handle the 'done' event to get notified when
       the related request is done.
@@ -184,13 +188,13 @@
 
     <event name="done" type="destructor">
       <description summary="done event">
-	Notify the client when the related request is done.
+        Notify the client when the related request is done.
       </description>
       <arg name="callback_data" type="uint" summary="request-specific data for the callback"/>
     </event>
   </interface>
 
-  <interface name="wl_compositor" version="6">
+  <interface name="wl_compositor" version="7">
     <description summary="the compositor singleton">
       A compositor.  This object is a singleton global.  The
       compositor is in charge of combining the contents of multiple
@@ -199,20 +203,28 @@
 
     <request name="create_surface">
       <description summary="create new surface">
-	Ask the compositor to create a new surface.
+        Ask the compositor to create a new surface.
       </description>
       <arg name="id" type="new_id" interface="wl_surface" summary="the new surface"/>
     </request>
 
     <request name="create_region">
       <description summary="create new region">
-	Ask the compositor to create a new region.
+        Ask the compositor to create a new region.
       </description>
       <arg name="id" type="new_id" interface="wl_region" summary="the new region"/>
     </request>
+
+    <!-- Version 7 additions -->
+
+    <request name="release" type="destructor" since="7">
+      <description summary="destroy wl_compositor">
+        This request destroys the wl_compositor. This has no effect on any other objects.
+      </description>
+    </request>
   </interface>
 
-  <interface name="wl_shm_pool" version="2">
+  <interface name="wl_shm_pool" version="3">
     <description summary="a shared memory pool">
       The wl_shm_pool object encapsulates a piece of memory shared
       between the compositor and client.  Through the wl_shm_pool
@@ -223,19 +235,27 @@
       a surface or for many small buffers.
     </description>
 
+    <enum name="error" since="3">
+      <description summary="wl_shm_pool error values">
+        These errors can be emitted in response to wl_shm_pool requests.
+      </description>
+      <entry name="invalid_format" value="0" summary="buffer format is not known"/>
+      <entry name="invalid_stride" value="1" summary="invalid size or stride during buffer creation"/>
+    </enum>
+
     <request name="create_buffer">
       <description summary="create a buffer from the pool">
-	Create a wl_buffer object from the pool.
+        Create a wl_buffer object from the pool.
 
-	The buffer is created offset bytes into the pool and has
-	width and height as specified.  The stride argument specifies
-	the number of bytes from the beginning of one row to the beginning
-	of the next.  The format is the pixel format of the buffer and
-	must be one of those advertised through the wl_shm.format event.
+        The buffer is created offset bytes into the pool and has
+        width and height as specified.  The stride argument specifies
+        the number of bytes from the beginning of one row to the beginning
+        of the next.  The format is the pixel format of the buffer and
+        must be one of those advertised through the wl_shm.format event.
 
-	A buffer will keep a reference to the pool it was created from
-	so it is valid to destroy the pool immediately after creating
-	a buffer from it.
+        A buffer will keep a reference to the pool it was created from
+        so it is valid to destroy the pool immediately after creating
+        a buffer from it.
       </description>
       <arg name="id" type="new_id" interface="wl_buffer" summary="buffer to create"/>
       <arg name="offset" type="int" summary="buffer byte offset within the pool"/>
@@ -247,32 +267,32 @@
 
     <request name="destroy" type="destructor">
       <description summary="destroy the pool">
-	Destroy the shared memory pool.
+        Destroy the shared memory pool.
 
-	The mmapped memory will be released when all
-	buffers that have been created from this pool
-	are gone.
+        The mmapped memory will be released when all
+        buffers that have been created from this pool
+        are gone.
       </description>
     </request>
 
     <request name="resize">
       <description summary="change the size of the pool mapping">
-	This request will cause the server to remap the backing memory
-	for the pool from the file descriptor passed when the pool was
-	created, but using the new size.  This request can only be
-	used to make the pool bigger.
+        This request will cause the server to remap the backing memory
+        for the pool from the file descriptor passed when the pool was
+        created, but using the new size.  This request can only be
+        used to make the pool bigger.
 
-	This request only changes the amount of bytes that are mmapped
-	by the server and does not touch the file corresponding to the
-	file descriptor passed at creation time. It is the client's
-	responsibility to ensure that the file is at least as big as
-	the new pool size.
+        This request only changes the amount of bytes that are mmapped
+        by the server and does not touch the file corresponding to the
+        file descriptor passed at creation time. It is the client's
+        responsibility to ensure that the file is at least as big as
+        the new pool size.
       </description>
       <arg name="size" type="int" summary="new size of the pool, in bytes"/>
     </request>
   </interface>
 
-  <interface name="wl_shm" version="2">
+  <interface name="wl_shm" version="3">
     <description summary="shared memory support">
       A singleton global object that provides support for shared
       memory.
@@ -285,32 +305,33 @@
       that can be used for buffers.
     </description>
 
-    <enum name="error">
+    <enum name="error" since="3">
       <description summary="wl_shm error values">
-	These errors can be emitted in response to wl_shm requests.
+        These errors can be emitted in response to wl_shm requests.
       </description>
-      <entry name="invalid_format" value="0" summary="buffer format is not known"/>
-      <entry name="invalid_stride" value="1" summary="invalid size or stride during pool or buffer creation"/>
+      <entry name="invalid_format" value="0" summary="buffer format is not known" deprecated-since="3"/>
+      <entry name="invalid_stride" value="1" summary="invalid size or stride during pool creation"/>
       <entry name="invalid_fd" value="2" summary="mmapping the file descriptor failed"/>
     </enum>
 
     <enum name="format">
       <description summary="pixel formats">
-	This describes the memory layout of an individual pixel.
+        This describes the memory layout of an individual pixel.
 
-	All renderers should support argb8888 and xrgb8888 but any other
-	formats are optional and may not be supported by the particular
-	renderer in use.
+        All renderers should support argb8888 and xrgb8888 but any other
+        formats are optional and may not be supported by the particular
+        renderer in use.
 
-	The drm format codes match the macros defined in drm_fourcc.h, except
-	argb8888 and xrgb8888. The formats actually supported by the compositor
-	will be reported by the format event.
+        The drm format codes match the macros defined in drm_fourcc.h, except
+        argb8888 and xrgb8888. The formats actually supported by the compositor
+        will be reported by the format event. See drm_fourcc.h for more detailed
+        format descriptions.
 
-	For all wl_shm formats and unless specified in another protocol
-	extension, pre-multiplied alpha is used for pixel values.
+        For all wl_shm formats and unless specified in another protocol
+        extension, pre-multiplied alpha is used for pixel values.
       </description>
       <!-- Note to protocol writers: don't update this list manually, instead
-	   run the automated script that keeps it in sync with drm_fourcc.h. -->
+           run the automated script that keeps it in sync with drm_fourcc.h. -->
       <entry name="argb8888" value="0" summary="32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian"/>
       <entry name="xrgb8888" value="1" summary="32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian"/>
       <entry name="c8" value="0x20203843" summary="8-bit color index format, [7:0] C"/>
@@ -322,7 +343,7 @@
       <entry name="bgrx4444" value="0x32315842" summary="16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian"/>
       <entry name="argb4444" value="0x32315241" summary="16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian"/>
       <entry name="abgr4444" value="0x32314241" summary="16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian"/>
-      <entry name="rgba4444" value="0x32314152" summary="16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian"/>
+      <entry name="rgba4444" value="0x32314152" summary="16-bit RGBA format, [15:0] R:G:B:A 4:4:4:4 little endian"/>
       <entry name="bgra4444" value="0x32314142" summary="16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian"/>
       <entry name="xrgb1555" value="0x35315258" summary="16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian"/>
       <entry name="xbgr1555" value="0x35314258" summary="16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian"/>
@@ -434,15 +455,40 @@
       <entry name="avuy8888" value="0x59555641" summary="[31:0] A:Cr:Cb:Y 8:8:8:8 little endian"/>
       <entry name="xvuy8888" value="0x59555658" summary="[31:0] X:Cr:Cb:Y 8:8:8:8 little endian"/>
       <entry name="p030" value="0x30333050" summary="2x2 subsampled Cr:Cb plane 10 bits per channel packed"/>
+      <entry name="rgb161616" value="0x38344752" summary="[47:0] R:G:B 16:16:16 little endian"/>
+      <entry name="bgr161616" value="0x38344742" summary="[47:0] B:G:R 16:16:16 little endian"/>
+      <entry name="r16f" value="0x48202052" summary="[15:0] R 16 little endian"/>
+      <entry name="gr1616f" value="0x48205247" summary="[31:0] G:R 16:16 little endian"/>
+      <entry name="bgr161616f" value="0x48524742" summary="[47:0] B:G:R 16:16:16 little endian"/>
+      <entry name="r32f" value="0x46202052" summary="[31:0] R 32 little endian"/>
+      <entry name="gr3232f" value="0x46205247" summary="[63:0] G:R 32:32 little endian"/>
+      <entry name="bgr323232f" value="0x46524742" summary="[95:0] B:G:R 32:32:32 little endian"/>
+      <entry name="abgr32323232f" value="0x46384241" summary="[127:0] A:B:G:R 32:32:32:32 little endian"/>
+      <entry name="nv20" value="0x3032564e" summary="2x1 subsampled Cr:Cb plane"/>
+      <entry name="nv30" value="0x3033564e" summary="non-subsampled Cr:Cb plane"/>
+      <entry name="s010" value="0x30313053" summary="2x2 subsampled Cb (1) and Cr (2) planes 10 bits per channel"/>
+      <entry name="s210" value="0x30313253" summary="2x1 subsampled Cb (1) and Cr (2) planes 10 bits per channel"/>
+      <entry name="s410" value="0x30313453" summary="non-subsampled Cb (1) and Cr (2) planes 10 bits per channel"/>
+      <entry name="s012" value="0x32313053" summary="2x2 subsampled Cb (1) and Cr (2) planes 12 bits per channel"/>
+      <entry name="s212" value="0x32313253" summary="2x1 subsampled Cb (1) and Cr (2) planes 12 bits per channel"/>
+      <entry name="s412" value="0x32313453" summary="non-subsampled Cb (1) and Cr (2) planes 12 bits per channel"/>
+      <entry name="s016" value="0x36313053" summary="2x2 subsampled Cb (1) and Cr (2) planes 16 bits per channel"/>
+      <entry name="s216" value="0x36313253" summary="2x1 subsampled Cb (1) and Cr (2) planes 16 bits per channel"/>
+      <entry name="s416" value="0x36313453" summary="non-subsampled Cb (1) and Cr (2) planes 16 bits per channel"/>
+      <entry name="xvuy2101010" value="0x30335958" summary="[31:0] x:Cr:Cb:Y 2:10:10:10 little endian"/>
+      <entry name="p230" value="0x30333250" summary="2x1 subsampled Cr:Cb plane 10 bits per channel packed"/>
+      <entry name="t430" value="0x30333454"/>
+      <entry name="y8" value="0x59455247" summary="8-bit Y-only"/>
+      <entry name="xyyy2101010" value="0x34415059" summary="[31:0] x:Y2:Y1:Y0 2:10:10:10 little endian"/>
     </enum>
 
     <request name="create_pool">
       <description summary="create a shm pool">
-	Create a new wl_shm_pool object.
+        Create a new wl_shm_pool object.
 
-	The pool can be used to create shared memory based buffer
-	objects.  The server will mmap size bytes of the passed file
-	descriptor, to use as backing memory for the pool.
+        The pool can be used to create shared memory based buffer
+        objects.  The server will mmap size bytes of the passed file
+        descriptor, to use as backing memory for the pool.
       </description>
       <arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
       <arg name="fd" type="fd" summary="file descriptor for the pool"/>
@@ -451,9 +497,13 @@
 
     <event name="format">
       <description summary="pixel format description">
-	Informs the client about a valid pixel format that
-	can be used for buffers. Known formats include
-	argb8888 and xrgb8888.
+        Informs the client about a valid pixel format that
+        can be used for buffers. Known formats include
+        argb8888 and xrgb8888.
+
+        Extensions to drm_fourcc.h (or the format enum) do not require
+        increasing the wl_shm version; as a result, clients may receive format
+        codes which were not in the list at the time the client was made.
       </description>
       <arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
     </event>
@@ -462,15 +512,15 @@
 
     <request name="release" type="destructor" since="2">
       <description summary="release the shm object">
-	Using this request a client can tell the server that it is not going to
-	use the shm object anymore.
+        Using this request a client can tell the server that it is not going to
+        use the shm object anymore.
 
-	Objects created via this interface remain unaffected.
+        Objects created via this interface remain unaffected.
       </description>
     </request>
   </interface>
 
-  <interface name="wl_buffer" version="1">
+  <interface name="wl_buffer" version="1" frozen="true">
     <description summary="content for a wl_surface">
       A buffer provides the content for a wl_surface. Buffers are
       created through factory interfaces such as wl_shm, wp_linux_buffer_params
@@ -491,34 +541,34 @@
 
     <request name="destroy" type="destructor">
       <description summary="destroy a buffer">
-	Destroy a buffer. If and how you need to release the backing
-	storage is defined by the buffer factory interface.
+        Destroy a buffer. If and how you need to release the backing
+        storage is defined by the buffer factory interface.
 
-	For possible side-effects to a surface, see wl_surface.attach.
+        For possible side-effects to a surface, see wl_surface.attach.
       </description>
     </request>
 
     <event name="release">
       <description summary="compositor releases buffer">
-	Sent when this wl_buffer is no longer used by the compositor.
+        Sent when this wl_buffer is no longer used by the compositor.
 
-	For more information on when release events may or may not be sent,
-	and what consequences it has, please see the description of
-	wl_surface.attach.
+        For more information on when release events may or may not be sent,
+        and what consequences it has, please see the description of
+        wl_surface.attach.
 
-	If a client receives a release event before the frame callback
-	requested in the same wl_surface.commit that attaches this
-	wl_buffer to a surface, then the client is immediately free to
-	reuse the buffer and its backing storage, and does not need a
-	second buffer for the next surface content update. Typically
-	this is possible, when the compositor maintains a copy of the
-	wl_surface contents, e.g. as a GL texture. This is an important
-	optimization for GL(ES) compositors with wl_shm clients.
+        If a client receives a release event before the frame callback
+        requested in the same wl_surface.commit that attaches this
+        wl_buffer to a surface, then the client is immediately free to
+        reuse the buffer and its backing storage, and does not need a
+        second buffer for the next surface content update. Typically
+        this is possible, when the compositor maintains a copy of the
+        wl_surface contents, e.g. as a GL texture. This is an important
+        optimization for GL(ES) compositors with wl_shm clients.
       </description>
     </event>
   </interface>
 
-  <interface name="wl_data_offer" version="3">
+  <interface name="wl_data_offer" version="4">
     <description summary="offer to transfer data">
       A wl_data_offer represents a piece of data offered for transfer
       by another client (the source client).  It is used by the
@@ -530,31 +580,31 @@
 
     <enum name="error">
       <entry name="invalid_finish" value="0"
-	     summary="finish request was called untimely"/>
+             summary="finish request was called untimely"/>
       <entry name="invalid_action_mask" value="1"
-	     summary="action mask contains invalid values"/>
+             summary="action mask contains invalid values"/>
       <entry name="invalid_action" value="2"
-	     summary="action argument has an invalid value"/>
+             summary="action argument has an invalid value"/>
       <entry name="invalid_offer" value="3"
-	     summary="offer doesn't accept this request"/>
+             summary="offer doesn't accept this request"/>
     </enum>
 
     <request name="accept">
       <description summary="accept one of the offered mime types">
-	Indicate that the client can accept the given mime type, or
-	NULL for not accepted.
+        Indicate that the client can accept the given mime type, or
+        NULL for not accepted.
 
-	For objects of version 2 or older, this request is used by the
-	client to give feedback whether the client can receive the given
-	mime type, or NULL if none is accepted; the feedback does not
-	determine whether the drag-and-drop operation succeeds or not.
+        For objects of version 2 or older, this request is used by the
+        client to give feedback whether the client can receive the given
+        mime type, or NULL if none is accepted; the feedback does not
+        determine whether the drag-and-drop operation succeeds or not.
 
-	For objects of version 3 or newer, this request determines the
-	final result of the drag-and-drop operation. If the end result
-	is that no mime types were accepted, the drag-and-drop operation
-	will be cancelled and the corresponding drag source will receive
-	wl_data_source.cancelled. Clients may still use this event in
-	conjunction with wl_data_source.action for feedback.
+        For objects of version 3 or newer, this request determines the
+        final result of the drag-and-drop operation. If the end result
+        is that no mime types were accepted, the drag-and-drop operation
+        will be cancelled and the corresponding drag source will receive
+        wl_data_source.cancelled. Clients may still use this event in
+        conjunction with wl_data_source.action for feedback.
       </description>
       <arg name="serial" type="uint" summary="serial number of the accept request"/>
       <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the client"/>
@@ -562,21 +612,21 @@
 
     <request name="receive">
       <description summary="request that the data is transferred">
-	To transfer the offered data, the client issues this request
-	and indicates the mime type it wants to receive.  The transfer
-	happens through the passed file descriptor (typically created
-	with the pipe system call).  The source client writes the data
-	in the mime type representation requested and then closes the
-	file descriptor.
-
-	The receiving client reads from the read end of the pipe until
-	EOF and then closes its end, at which point the transfer is
-	complete.
-
-	This request may happen multiple times for different mime types,
-	both before and after wl_data_device.drop. Drag-and-drop destination
-	clients may preemptively fetch data or examine it more closely to
-	determine acceptance.
+        To transfer the offered data,

(Patch may be truncated, please check the link at the top of this post.)