diff --git a/.gitignore b/.gitignore index fb318887a069..c4876b64ef51 100644 --- a/.gitignore +++ b/.gitignore @@ -242,6 +242,8 @@ gfx/common/wayland/single-pixel-buffer-v1.h gfx/common/wayland/single-pixel-buffer-v1.c gfx/common/wayland/xdg-toplevel-icon-v1.h gfx/common/wayland/xdg-toplevel-icon-v1.c +gfx/common/wayland/xdg-toplevel-tag-v1.h +gfx/common/wayland/xdg-toplevel-tag-v1.c gfx/common/wayland/webos-foreign.c gfx/common/wayland/webos-foreign.h gfx/common/wayland/webos-input-manager.c diff --git a/Makefile.common b/Makefile.common index 19fe73b404ab..85a62a75b1f9 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1275,6 +1275,7 @@ ifeq ($(HAVE_WAYLAND), 1) gfx/common/wayland/fractional-scale-v1.o \ gfx/common/wayland/viewporter.o \ gfx/common/wayland/xdg-toplevel-icon-v1.o \ + gfx/common/wayland/xdg-toplevel-tag-v1.o \ gfx/common/wayland/xdg-shell.o \ gfx/common/wayland/idle-inhibit-unstable-v1.o \ gfx/common/wayland/xdg-decoration-unstable-v1.o \ diff --git a/deps/wayland-protocols/staging/xdg-toplevel-tag/README b/deps/wayland-protocols/staging/xdg-toplevel-tag/README new file mode 100644 index 000000000000..b4910eef486f --- /dev/null +++ b/deps/wayland-protocols/staging/xdg-toplevel-tag/README @@ -0,0 +1,4 @@ +Toplevel tag protocol + +Maintainers: +Xaver Hugl diff --git a/deps/wayland-protocols/staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml b/deps/wayland-protocols/staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml new file mode 100644 index 000000000000..5e20bdf45f81 --- /dev/null +++ b/deps/wayland-protocols/staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml @@ -0,0 +1,85 @@ + + + + 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 manager 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, 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. + + + + + + + + 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. + + + + + + + diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh index 327c1c158f5c..841142092c49 100755 --- a/gfx/common/wayland/generate_wayland_protos.sh +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -82,6 +82,7 @@ generate_source 'unstable/tablet' 'tablet-unstable-v2' generate_source 'staging/content-type' 'content-type-v1' generate_source 'staging/single-pixel-buffer' 'single-pixel-buffer-v1' generate_source 'staging/xdg-toplevel-icon' 'xdg-toplevel-icon-v1' +generate_source 'staging/xdg-toplevel-tag' 'xdg-toplevel-tag-v1' if [ -n "${CROSS_COMPILE:-}" ] && echo "${CROSS_COMPILE:-}" | grep -q "webos"; then if [ -z "${SDK_PATH:-}" ]; then diff --git a/gfx/common/wayland_common.c b/gfx/common/wayland_common.c index d1205360774e..30622c90f834 100644 --- a/gfx/common/wayland_common.c +++ b/gfx/common/wayland_common.c @@ -34,7 +34,8 @@ #define SPLASH_SHM_NAME "retroarch-wayland-vk-splash" -#define WINDOW_TITLE "RetroArch" +#define DEFAULT_WINDOW_TITLE "RetroArch" +#define MAIN_WINDOW_TAG "main window" #ifdef HAVE_LIBDECOR_H #include @@ -280,10 +281,10 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl) if (wl->wl_touch) wl_touch_destroy(wl->wl_touch); - if (wl->cursor.theme) - wl_cursor_theme_destroy(wl->cursor.theme); if (wl->cursor.surface) wl_surface_destroy(wl->cursor.surface); + if (wl->cursor.theme) + wl_cursor_theme_destroy(wl->cursor.theme); if (wl->viewport) wp_viewport_destroy(wl->viewport); @@ -293,12 +294,10 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl) zwp_idle_inhibitor_v1_destroy(wl->idle_inhibitor); if (wl->deco) zxdg_toplevel_decoration_v1_destroy(wl->deco); - if (wl->xdg_toplevel) - xdg_toplevel_destroy(wl->xdg_toplevel); - if (wl->xdg_toplevel_icon_manager) - xdg_toplevel_icon_manager_v1_destroy(wl->xdg_toplevel_icon_manager); if (wl->xdg_toplevel_icon) xdg_toplevel_icon_v1_destroy(wl->xdg_toplevel_icon); + if (wl->xdg_toplevel) + xdg_toplevel_destroy(wl->xdg_toplevel); if (wl->xdg_surface) xdg_surface_destroy(wl->xdg_surface); if (wl->surface) @@ -306,6 +305,10 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl) if (wl->deco_manager) zxdg_decoration_manager_v1_destroy(wl->deco_manager); + if (wl->xdg_toplevel_icon_manager) + xdg_toplevel_icon_manager_v1_destroy(wl->xdg_toplevel_icon_manager); + if (wl->xdg_toplevel_tag_manager) + xdg_toplevel_tag_manager_v1_destroy(wl->xdg_toplevel_tag_manager); if (wl->idle_inhibit_manager) zwp_idle_inhibit_manager_v1_destroy(wl->idle_inhibit_manager); else @@ -388,6 +391,7 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl) wl->xdg_toplevel = NULL; wl->xdg_toplevel_icon = NULL; wl->xdg_toplevel_icon_manager = NULL; + wl->xdg_toplevel_tag_manager = NULL; wl->deco = NULL; wl->idle_inhibitor = NULL; wl->wl_touch = NULL; @@ -833,6 +837,11 @@ bool gfx_ctx_wl_init_common( RARCH_LOG("[Wayland] Compositor doesn't support the %s protocol.\n", xdg_toplevel_icon_manager_v1_interface.name); } + if (!wl->xdg_toplevel_tag_manager) + { + RARCH_LOG("[Wayland] Compositor doesn't support the %s protocol.\n", xdg_toplevel_tag_manager_v1_interface.name); + } + wl->surface = wl_compositor_create_surface(wl->compositor); if (wl->viewporter) wl->viewport = wp_viewporter_get_viewport(wl->viewporter, wl->surface); @@ -864,14 +873,23 @@ bool gfx_ctx_wl_init_common( return false; } + struct xdg_toplevel *xdg_toplevel = wl->libdecor_frame_get_xdg_toplevel(wl->libdecor_frame); + if (wl->xdg_toplevel_icon_manager) { - struct xdg_toplevel *xdg_toplevel = wl->libdecor_frame_get_xdg_toplevel(wl->libdecor_frame); wl_create_toplevel_icon(wl, xdg_toplevel); } + if (wl->xdg_toplevel_tag_manager) + { + xdg_toplevel_tag_manager_v1_set_toplevel_tag( + wl->xdg_toplevel_tag_manager, xdg_toplevel, MAIN_WINDOW_TAG); + xdg_toplevel_tag_manager_v1_set_toplevel_description( + wl->xdg_toplevel_tag_manager, xdg_toplevel, DEFAULT_WINDOW_TITLE " " MAIN_WINDOW_TAG); + } + wl->libdecor_frame_set_app_id(wl->libdecor_frame, WAYLAND_APP_ID); - wl->libdecor_frame_set_title(wl->libdecor_frame, WINDOW_TITLE); + wl->libdecor_frame_set_title(wl->libdecor_frame, DEFAULT_WINDOW_TITLE); wl->libdecor_frame_map(wl->libdecor_frame); /* Waiting for libdecor to be configured before starting to draw */ @@ -897,7 +915,7 @@ bool gfx_ctx_wl_init_common( xdg_toplevel_add_listener(wl->xdg_toplevel, &toplevel_listener->xdg_toplevel_listener, wl); xdg_toplevel_set_app_id(wl->xdg_toplevel, WAYLAND_APP_ID); - xdg_toplevel_set_title(wl->xdg_toplevel, WINDOW_TITLE); + xdg_toplevel_set_title(wl->xdg_toplevel, DEFAULT_WINDOW_TITLE); if (wl->deco_manager) wl->deco = zxdg_decoration_manager_v1_get_toplevel_decoration( @@ -906,6 +924,14 @@ bool gfx_ctx_wl_init_common( if (wl->xdg_toplevel_icon_manager) wl_create_toplevel_icon(wl, wl->xdg_toplevel); + if (wl->xdg_toplevel_tag_manager) + { + xdg_toplevel_tag_manager_v1_set_toplevel_tag( + wl->xdg_toplevel_tag_manager, wl->xdg_toplevel, MAIN_WINDOW_TAG); + xdg_toplevel_tag_manager_v1_set_toplevel_description( + wl->xdg_toplevel_tag_manager, wl->xdg_toplevel, DEFAULT_WINDOW_TITLE " " MAIN_WINDOW_TAG); + } + /* Waiting for xdg_toplevel to be configured before starting to draw */ wl_surface_commit(wl->surface); wl->configured = true; diff --git a/input/common/wayland_common.c b/input/common/wayland_common.c index 426a129ceac2..ebdf6e1c7976 100644 --- a/input/common/wayland_common.c +++ b/input/common/wayland_common.c @@ -809,6 +809,10 @@ static void wl_registry_handle_global(void *data, struct wl_registry *reg, wl->xdg_toplevel_icon_manager = (struct xdg_toplevel_icon_manager_v1*) wl_registry_bind( reg, id, &xdg_toplevel_icon_manager_v1_interface, MIN(version, 1)); + else if (string_is_equal(interface, xdg_toplevel_tag_manager_v1_interface.name) && found++) + wl->xdg_toplevel_tag_manager = (struct xdg_toplevel_tag_manager_v1*) + wl_registry_bind( + reg, id, &xdg_toplevel_tag_manager_v1_interface, MIN(version, 1)); if (found > 1) RARCH_LOG("[Wayland] Registered interface %s at version %u.\n", diff --git a/input/common/wayland_common.h b/input/common/wayland_common.h index 4e67b105d35f..a41d7e99e261 100644 --- a/input/common/wayland_common.h +++ b/input/common/wayland_common.h @@ -45,6 +45,7 @@ #include "../../gfx/common/wayland/xdg-decoration-unstable-v1.h" #include "../../gfx/common/wayland/xdg-shell.h" #include "../../gfx/common/wayland/xdg-toplevel-icon-v1.h" +#include "../../gfx/common/wayland/xdg-toplevel-tag-v1.h" #ifdef WEBOS #include "wayland_common_webos.h" @@ -166,6 +167,7 @@ typedef struct gfx_ctx_wayland_data struct xdg_toplevel *xdg_toplevel; struct xdg_toplevel_icon_v1 *xdg_toplevel_icon; struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager; + struct xdg_toplevel_tag_manager_v1 *xdg_toplevel_tag_manager; struct wl_keyboard *wl_keyboard; struct wl_pointer *wl_pointer; struct zwp_relative_pointer_v1 *wl_relative_pointer; diff --git a/qb/config.libs.sh b/qb/config.libs.sh index d5315b83acc9..c2086c441e1b 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -564,7 +564,7 @@ check_header '' XSHM X11/Xlib.h X11/extensions/XShm.h check_val '' XKBCOMMON -lxkbcommon '' xkbcommon 0.3.2 '' false check_val '' WAYLAND '-lwayland-egl -lwayland-client' '' wayland-egl 10.1.0 '' false check_val '' WAYLAND_CURSOR -lwayland-cursor '' wayland-cursor 1.12 '' false -check_pkgconf WAYLAND_PROTOS wayland-protocols 1.37 +check_pkgconf WAYLAND_PROTOS wayland-protocols 1.43 check_pkgconf WAYLAND_SCANNER wayland-scanner '1.15 1.12' if [ "$HAVE_WAYLAND_SCANNER" = yes ] &&