From b800a5ea2d47f1c7e4b7278e43cfcc2821c4cf00 Mon Sep 17 00:00:00 2001 From: Bilal Elmoussaoui Date: Wed, 13 Nov 2024 13:33:10 +0100 Subject: [PATCH] gdk/wayland: Implement toplevel tag protocol The toplevel tag would an application developer to tag a toplevel surface with a tag. When combined with the application-id, the compositor can use that information to identify specific windows and use it for configurability/scriptability. The protocol: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/238 --- gdk/wayland/gdkdisplay-wayland.c | 8 +++ gdk/wayland/gdkdisplay-wayland.h | 1 + gdk/wayland/gdktoplevel-wayland.c | 47 ++++++++++++- gdk/wayland/gdkwaylandtoplevel.h | 4 ++ gdk/wayland/meson.build | 5 ++ gdk/wayland/protocol/xdg-toplevel-tag-v1.xml | 70 ++++++++++++++++++++ gtk/inspector/general.c | 1 + 7 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 gdk/wayland/protocol/xdg-toplevel-tag-v1.xml diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 40e5881f66..6ea71b2e0b 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -63,6 +63,7 @@ #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "presentation-time-client-protocol.h" #include "xx-color-management-v4-client-protocol.h" +#include "xdg-toplevel-tag-v1-client-protocol.h" #include "wm-button-layout-translation.h" @@ -554,6 +555,12 @@ gdk_registry_handle_global (void *data, wl_registry_bind (display_wayland->wl_registry, id, &xdg_system_bell_v1_interface, 1); } + else if (strcmp (interface, xdg_toplevel_tag_manager_v1_interface.name) == 0) + { + display_wayland->xdg_toplevel_tag = + wl_registry_bind (display_wayland->wl_registry, id, + &xdg_toplevel_tag_manager_v1_interface, 1); + } g_hash_table_insert (display_wayland->known_globals, GUINT_TO_POINTER (id), g_strdup (interface)); @@ -770,6 +777,7 @@ gdk_wayland_display_dispose (GObject *object) g_clear_pointer (&display_wayland->dmabuf_formats_info, dmabuf_formats_info_free); g_clear_pointer (&display_wayland->color, gdk_wayland_color_free); g_clear_pointer (&display_wayland->system_bell, xdg_system_bell_v1_destroy); + g_clear_pointer (&display_wayland->xdg_toplevel_tag, xdg_toplevel_tag_manager_v1_destroy); g_clear_pointer (&display_wayland->shm, wl_shm_destroy); g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 8f561583fe..ac26c2f2ee 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -126,6 +126,7 @@ struct _GdkWaylandDisplay struct wp_viewporter *viewporter; struct wp_presentation *presentation; struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer; + struct xdg_toplevel_tag_manager_v1 *xdg_toplevel_tag; GdkWaylandColor *color; GList *async_roundtrips; diff --git a/gdk/wayland/gdktoplevel-wayland.c b/gdk/wayland/gdktoplevel-wayland.c index f0b9fbec01..32abfb2f7d 100644 --- a/gdk/wayland/gdktoplevel-wayland.c +++ b/gdk/wayland/gdktoplevel-wayland.c @@ -38,6 +38,7 @@ #include #include #include +#include "xdg-toplevel-tag-v1-client-protocol.h" #include #include @@ -1257,7 +1258,7 @@ gdk_wayland_toplevel_set_transient_for (GdkWaylandToplevel *toplevel, #define LAST_PROP 1 -static void +static void gdk_wayland_toplevel_set_decorated (GdkWaylandToplevel *self, gboolean decorated) { @@ -2480,6 +2481,50 @@ gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel, } } + +/** + * gdk_wayland_toplevel_set_tag: + * @toplevel: (type GdkWaylandToplevel): a `GdkToplevel` to set the tag for + * @tag: A preferably human-readable tag + * + * Set a tag to the toplevel allowing to uniquely identify it from the compositor + * side. + * + * The tag along with the application ID can be used to create a unique identifier + * per app / window. + * + * The tag may be shown to the user in UI, so it's preferable for + * it to be human readable. Suitable tags would for example be + * “main window”, “settings”, “e-mail composer” or similar. + * + * The tag does not need to be unique across applications. + + * Returns: whether the tag was set. + * + * Since: 4.18 + */ +gboolean +gdk_wayland_toplevel_set_tag (GdkToplevel *toplevel, + const char *tag) +{ + GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel); + GdkSurface *surface = GDK_SURFACE (toplevel); + GdkDisplay *display = gdk_surface_get_display (surface); + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + + if (!display_wayland->xdg_toplevel_tag) + { + g_warning ("Server is missing xdg_toplevel_tag support"); + return FALSE; + } + + xdg_toplevel_tag_manager_v1_set_toplevel_tag (display_wayland->xdg_toplevel_tag, + wayland_toplevel->display_server.xdg_toplevel, + tag); + + return TRUE; +} + gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel) { diff --git a/gdk/wayland/gdkwaylandtoplevel.h b/gdk/wayland/gdkwaylandtoplevel.h index 0240f9d19f..96ff8a7e39 100644 --- a/gdk/wayland/gdkwaylandtoplevel.h +++ b/gdk/wayland/gdkwaylandtoplevel.h @@ -67,4 +67,8 @@ GDK_AVAILABLE_IN_ALL void gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel, const char *application_id); +GDK_AVAILABLE_IN_4_18 +gboolean gdk_wayland_toplevel_set_tag (GdkToplevel *toplevel, + const char *tag); + G_END_DECLS diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index 498302984e..6ca91437a3 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -156,6 +156,11 @@ proto_sources = [ 'stability': 'private', 'version': 1, }, + { + 'name': 'xdg-toplevel-tag', + 'stability': 'private', + 'version': 1, + }, ] gdk_wayland_gen_headers = [] diff --git a/gdk/wayland/protocol/xdg-toplevel-tag-v1.xml b/gdk/wayland/protocol/xdg-toplevel-tag-v1.xml new file mode 100644 index 0000000000..d8f4107b04 --- /dev/null +++ b/gdk/wayland/protocol/xdg-toplevel-tag-v1.xml @@ -0,0 +1,70 @@ + + + + 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. + + + + + 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. + + + + + Destroy this toplevel tag factory object. This request has no other effects. + + + + + + + + + + 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. 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. + + If a tag is set at all, the client must set the tag as part of the initial commit on the + associated toplevel. If the toplevel is already mapped, or the following wl_surface.commit + after this request maps the surface, the tag_on_mapped error is emitted. + + + + + + + diff --git a/gtk/inspector/general.c b/gtk/inspector/general.c index ccf8769370..d478c111fa 100644 --- a/gtk/inspector/general.c +++ b/gtk/inspector/general.c @@ -743,6 +743,7 @@ add_wayland_protocols (GdkDisplay *display, append_wayland_protocol_row (gen, (struct wl_proxy *)d->single_pixel_buffer); append_wayland_protocol_row (gen, d->color ? gdk_wayland_color_get_color_manager (d->color) : NULL); append_wayland_protocol_row (gen, (struct wl_proxy *)d->system_bell); + append_wayland_protocol_row (gen, (struct wl_proxy *)d->xdg_toplevel_tag); } } #endif