wayland: Add the xdg-foreign-unstable-v2 protocol

Add the xdg-foreign-unstable-v2 protocol and use it to create export handles for toplevel windows, which will be used when an external component, such as the file chooser portal, requires it.
This commit is contained in:
Frank Praznik
2024-03-15 11:36:05 -04:00
parent db31367999
commit 19764ffcc8
6 changed files with 279 additions and 28 deletions

View File

@@ -57,6 +57,7 @@
#include "viewporter-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "xdg-foreign-unstable-v2-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
@@ -1078,6 +1079,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
if (d->input) {
Wayland_CreateCursorShapeDevice(d->input);
}
} else if (SDL_strcmp(interface, "zxdg_exporter_v2") == 0) {
d->zxdg_exporter_v2 = wl_registry_bind(d->registry, id, &zxdg_exporter_v2_interface, 1);
} else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) {
d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1);
kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d);
@@ -1331,6 +1334,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
data->cursor_shape_manager = NULL;
}
if (data->zxdg_exporter_v2) {
zxdg_exporter_v2_destroy(data->zxdg_exporter_v2);
data->zxdg_exporter_v2 = NULL;
}
if (data->kde_output_order) {
Wayland_FlushOutputOrder(data);
kde_output_order_v1_destroy(data->kde_output_order);

View File

@@ -79,6 +79,7 @@ struct SDL_VideoData
struct wp_viewporter *viewporter;
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
struct zwp_input_timestamps_manager_v1 *input_timestamps_manager;
struct zxdg_exporter_v2 *zxdg_exporter_v2;
struct kde_output_order_v1 *kde_output_order;
struct xkb_context *xkb_context;

View File

@@ -38,6 +38,7 @@
#include "xdg-activation-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "fractional-scale-v1-client-protocol.h"
#include "xdg-foreign-unstable-v2-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
@@ -1484,6 +1485,21 @@ static struct wl_callback_listener show_hide_sync_listener = {
show_hide_sync_handler
};
static void exported_handle_handler(void *data, struct zxdg_exported_v2 *zxdg_exported_v2, const char *handle)
{
SDL_WindowData *wind = (SDL_WindowData*)data;
SDL_PropertiesID props = SDL_GetWindowProperties(wind->sdlwindow);
SDL_free(wind->export_handle);
wind->export_handle = SDL_strdup(handle);
SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_POINTER, wind->export_handle);
}
static struct zxdg_exported_v2_listener exported_v2_listener = {
exported_handle_handler
};
void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_VideoData *c = _this->driverdata;
@@ -1549,6 +1565,11 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, data->app_id);
libdecor_frame_map(data->shell_surface.libdecor.frame);
if (c->zxdg_exporter_v2) {
data->exported = zxdg_exporter_v2_export_toplevel(c->zxdg_exporter_v2, data->surface);
zxdg_exported_v2_add_listener(data->exported, &exported_v2_listener, data);
}
SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame));
SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame));
}
@@ -1623,6 +1644,12 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, data->app_id);
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
if (c->zxdg_exporter_v2) {
data->exported = zxdg_exporter_v2_export_toplevel(c->zxdg_exporter_v2, data->surface);
zxdg_exported_v2_add_listener(data->exported, &exported_v2_listener, data);
}
SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, data->shell_surface.xdg.roleobj.toplevel);
}
}
@@ -1699,7 +1726,6 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
Wayland_SetWindowResizable(_this, window, !!(window->flags & SDL_WINDOW_RESIZABLE));
Wayland_SetWindowBordered(_this, window, !(window->flags & SDL_WINDOW_BORDERLESS));
/* We're finally done putting the window together, raise if possible */
if (c->activation_manager) {
/* Note that we don't check for empty strings, as that is still
@@ -1798,6 +1824,17 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
wl_surface_commit(wind->surface);
}
/* Clean up the export handle. */
if (wind->exported) {
zxdg_exported_v2_destroy(wind->exported);
wind->exported = NULL;
SDL_free(wind->export_handle);
wind->export_handle = NULL;
SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_POINTER, NULL);
}
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame) {

View File

@@ -95,6 +95,7 @@ struct SDL_WindowData
struct xdg_activation_token_v1 *activation_token;
struct wp_viewport *viewport;
struct wp_fractional_scale_v1 *fractional_scale;
struct zxdg_exported_v2 *exported;
SDL_AtomicInt swap_interval_ready;
@@ -104,6 +105,7 @@ struct SDL_WindowData
SDL_Window *keyboard_focus;
char *app_id;
char *export_handle;
float windowed_scale_factor;
struct