Просмотр исходного кода

wayland: Add support for the toplevel tag protocol

Uses the same ID string as the session manager protocol.
Frank Praznik 1 неделя назад
Родитель
Сommit
b4b1cdeb27

+ 8 - 0
src/video/wayland/SDL_waylandvideo.c

@@ -71,6 +71,7 @@
 #include "pointer-gestures-unstable-v1-client-protocol.h"
 #include "pointer-gestures-unstable-v1-client-protocol.h"
 #include "single-pixel-buffer-v1-client-protocol.h"
 #include "single-pixel-buffer-v1-client-protocol.h"
 #include "xdg-session-management-v1-client-protocol.h"
 #include "xdg-session-management-v1-client-protocol.h"
+#include "xdg-toplevel-tag-v1-client-protocol.h"
 
 
 #ifdef HAVE_LIBDECOR_H
 #ifdef HAVE_LIBDECOR_H
 #include <libdecor.h>
 #include <libdecor.h>
@@ -1511,6 +1512,8 @@ static void handle_registry_global(void *data, struct wl_registry *registry, uin
         d->single_pixel_buffer_manager = wl_registry_bind(d->registry, id, &wp_single_pixel_buffer_manager_v1_interface, 1);
         d->single_pixel_buffer_manager = wl_registry_bind(d->registry, id, &wp_single_pixel_buffer_manager_v1_interface, 1);
     } else if (SDL_strcmp(interface, xdg_session_manager_v1_interface.name) == 0) {
     } else if (SDL_strcmp(interface, xdg_session_manager_v1_interface.name) == 0) {
         d->xdg_session_manager = wl_registry_bind(d->registry, id, &xdg_session_manager_v1_interface, 1);
         d->xdg_session_manager = wl_registry_bind(d->registry, id, &xdg_session_manager_v1_interface, 1);
+    } else if (SDL_strcmp(interface, xdg_toplevel_tag_manager_v1_interface.name) == 0) {
+        d->xdg_toplevel_tag_manager = wl_registry_bind(d->registry, id, &xdg_toplevel_tag_manager_v1_interface, 1);
     }
     }
 #ifdef SDL_WL_FIXES_VERSION
 #ifdef SDL_WL_FIXES_VERSION
     else if (SDL_strcmp(interface, wl_fixes_interface.name) == 0) {
     else if (SDL_strcmp(interface, wl_fixes_interface.name) == 0) {
@@ -1935,6 +1938,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
         data->xdg_session_manager = NULL;
         data->xdg_session_manager = NULL;
     }
     }
 
 
+    if (data->xdg_toplevel_tag_manager) {
+        xdg_toplevel_tag_manager_v1_destroy(data->xdg_toplevel_tag_manager);
+        data->xdg_toplevel_tag_manager = NULL;
+    }
+
     if (data->subcompositor) {
     if (data->subcompositor) {
         wl_subcompositor_destroy(data->subcompositor);
         wl_subcompositor_destroy(data->subcompositor);
         data->subcompositor = NULL;
         data->subcompositor = NULL;

+ 1 - 0
src/video/wayland/SDL_waylandvideo.h

@@ -88,6 +88,7 @@ struct SDL_VideoData
     struct zwp_pointer_gestures_v1 *zwp_pointer_gestures;
     struct zwp_pointer_gestures_v1 *zwp_pointer_gestures;
     struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager;
     struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager;
     struct xdg_session_manager_v1 *xdg_session_manager;
     struct xdg_session_manager_v1 *xdg_session_manager;
+    struct xdg_toplevel_tag_manager_v1 *xdg_toplevel_tag_manager;
 
 
     struct xdg_session_v1 *xdg_session;
     struct xdg_session_v1 *xdg_session;
     struct xkb_context *xkb_context;
     struct xkb_context *xkb_context;

+ 12 - 7
src/video/wayland/SDL_waylandwindow.c

@@ -50,6 +50,7 @@
 #include "xdg-toplevel-icon-v1-client-protocol.h"
 #include "xdg-toplevel-icon-v1-client-protocol.h"
 #include "color-management-v1-client-protocol.h"
 #include "color-management-v1-client-protocol.h"
 #include "xdg-session-management-v1-client-protocol.h"
 #include "xdg-session-management-v1-client-protocol.h"
+#include "xdg-toplevel-tag-v1-client-protocol.h"
 
 
 #ifdef HAVE_LIBDECOR_H
 #ifdef HAVE_LIBDECOR_H
 #include <libdecor.h>
 #include <libdecor.h>
@@ -2053,22 +2054,26 @@ bool Wayland_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool mod
 
 
 static void Wayland_RegisterToplevelForSession(SDL_WindowData *data)
 static void Wayland_RegisterToplevelForSession(SDL_WindowData *data)
 {
 {
-    SDL_VideoDevice *viddev = SDL_GetVideoDevice();
-    SDL_VideoData *viddata = viddev->internal;
-
     struct xdg_toplevel *toplevel = GetToplevelForWindow(data);
     struct xdg_toplevel *toplevel = GetToplevelForWindow(data);
     if (!toplevel) {
     if (!toplevel) {
         return;
         return;
     }
     }
 
 
-    if (viddata->xdg_session_manager) {
-        const char *id = SDL_GetStringProperty(data->sdlwindow->props, SDL_PROP_WINDOW_WAYLAND_WINDOW_ID_STRING, NULL);
-        if (id && *id != '\0') {
+    const char *id = SDL_GetStringProperty(data->sdlwindow->props, SDL_PROP_WINDOW_WAYLAND_WINDOW_ID_STRING, NULL);
+    if (id && *id != '\0') {
+        SDL_VideoDevice *viddev = SDL_GetVideoDevice();
+        SDL_VideoData *viddata = viddev->internal;
+
+        if (viddata->xdg_toplevel_tag_manager) {
+            xdg_toplevel_tag_manager_v1_set_toplevel_tag(viddata->xdg_toplevel_tag_manager, toplevel, id);
+        }
+
+        if (viddata->xdg_session_manager) {
             Wayland_CreateSession(viddata);
             Wayland_CreateSession(viddata);
 
 
             if (viddata->xdg_session) {
             if (viddata->xdg_session) {
                 CHECK_PARAM (true) {
                 CHECK_PARAM (true) {
-                    // Windows must not have a duplicate ID string, or a protocol error will result.
+                    // Windows added to a session must not have a duplicate ID string, or a protocol error will result.
                     for (SDL_Window *w = viddev->windows; w; w = w->next) {
                     for (SDL_Window *w = viddev->windows; w; w = w->next) {
                         SDL_WindowData *d = w->internal;
                         SDL_WindowData *d = w->internal;
                         if (d->session_id && SDL_strcmp(d->session_id, id) == 0) {
                         if (d->session_id && SDL_strcmp(d->session_id, id) == 0) {

+ 85 - 0
wayland-protocols/xdg-toplevel-tag-v1.xml

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="xdg_toplevel_tag_v1">
+  <copyright>
+    Copyright © 2024 Xaver Hugl
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <interface name="xdg_toplevel_tag_manager_v1" version="1">
+    <description summary="protocol for setting toplevel tags">
+      In order to make some window properties like position, size,
+      "always on top" or user defined rules for window behavior persistent, the
+      compositor needs some way to identify windows even after the application
+      has been restarted.
+      This protocol allows clients to make this possible by setting a tag for
+      toplevels.
+
+      Warning! The protocol described in this file is currently in the testing
+      phase. Backward compatible changes may be added together with the
+      corresponding interface version bump. Backward incompatible changes can
+      only be done by creating a new major version of the extension.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy toplevel tag object">
+        Destroy this toplevel tag manager object. This request has no other
+        effects.
+      </description>
+    </request>
+
+    <request name="set_toplevel_tag">
+      <description summary="set tag">
+        Set a tag for a toplevel. The tag may be shown to the user in UI, so
+        it's preferable for it to be human readable, but it must be suitable
+        for configuration files and should not be translated.
+        Suitable tags would for example be "main window", "settings",
+        "e-mail composer" or similar.
+
+        The tag does not need to be unique across applications, and the client
+        may set the same tag for multiple windows, for example if the user has
+        opened the same UI twice. How the potentially resulting conflicts are
+        handled is compositor policy.
+
+        The client should set the tag as part of the initial commit on the
+        associated toplevel, but it may set it at any time afterwards as well,
+        for example if the purpose of the toplevel changes.
+      </description>
+      <arg name="toplevel" type="object" interface="xdg_toplevel"/>
+      <arg name="tag" type="string" summary="untranslated tag"/>
+    </request>
+
+    <request name="set_toplevel_description">
+      <description summary="set description">
+        Set a description for a toplevel. This description may be shown to the
+        user in UI or read by a screen reader for accessibility purposes, and
+        should be translated.
+        It is recommended to make the description the translation of the tag.
+
+        The client should set the description as part of the initial commit on
+        the associated toplevel, but it may set it at any time afterwards as
+        well, for example if the purpose of the toplevel changes.
+      </description>
+      <arg name="toplevel" type="object" interface="xdg_toplevel"/>
+      <arg name="description" type="string" summary="translated description"/>
+    </request>
+  </interface>
+
+</protocol>