Simple Directmedia Layer

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.

+279 -28
+30 -27
include/SDL3/SDL_video.h
··· 1111 1111 * with the window 1112 1112 * - `SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER`: the xdg_toplevel role 1113 1113 * associated with the window 1114 + * - 'SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_POINTER': the export 1115 + * handle associated with the window 1114 1116 * - `SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER`: the xdg_popup role 1115 1117 * associated with the window 1116 1118 * - `SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER`: the xdg_positioner ··· 1136 1138 */ 1137 1139 extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); 1138 1140 1139 - #define SDL_PROP_WINDOW_SHAPE_POINTER "SDL.window.shape" 1140 - #define SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" 1141 - #define SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" 1142 - #define SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" 1143 - #define SDL_PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" 1144 - #define SDL_PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" 1145 - #define SDL_PROP_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" 1146 - #define SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" 1147 - #define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" 1148 - #define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" 1149 - #define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" 1150 - #define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" 1151 - #define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" 1152 - #define SDL_PROP_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" 1153 - #define SDL_PROP_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" 1154 - #define SDL_PROP_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" 1155 - #define SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" 1156 - #define SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" 1157 - #define SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" 1158 - #define SDL_PROP_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" 1159 - #define SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" 1160 - #define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" 1161 - #define SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" 1162 - #define SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" 1163 - #define SDL_PROP_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" 1164 - #define SDL_PROP_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" 1165 - #define SDL_PROP_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" 1141 + #define SDL_PROP_WINDOW_SHAPE_POINTER "SDL.window.shape" 1142 + #define SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" 1143 + #define SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" 1144 + #define SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" 1145 + #define SDL_PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" 1146 + #define SDL_PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" 1147 + #define SDL_PROP_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" 1148 + #define SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" 1149 + #define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" 1150 + #define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" 1151 + #define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" 1152 + #define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" 1153 + #define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" 1154 + #define SDL_PROP_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" 1155 + #define SDL_PROP_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" 1156 + #define SDL_PROP_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" 1157 + #define SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" 1158 + #define SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" 1159 + #define SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" 1160 + #define SDL_PROP_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" 1161 + #define SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" 1162 + #define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" 1163 + #define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_POINTER "SDL.window.wayland.xdg_toplevel_export_handle" 1164 + #define SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" 1165 + #define SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" 1166 + #define SDL_PROP_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" 1167 + #define SDL_PROP_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" 1168 + #define SDL_PROP_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" 1166 1169 1167 1170 /** 1168 1171 * Get the window flags.
+8
src/video/wayland/SDL_waylandvideo.c
··· 57 57 #include "viewporter-client-protocol.h" 58 58 #include "xdg-activation-v1-client-protocol.h" 59 59 #include "xdg-decoration-unstable-v1-client-protocol.h" 60 + #include "xdg-foreign-unstable-v2-client-protocol.h" 60 61 #include "xdg-output-unstable-v1-client-protocol.h" 61 62 #include "xdg-shell-client-protocol.h" 62 63 ··· 1078 1079 if (d->input) { 1079 1080 Wayland_CreateCursorShapeDevice(d->input); 1080 1081 } 1082 + } else if (SDL_strcmp(interface, "zxdg_exporter_v2") == 0) { 1083 + d->zxdg_exporter_v2 = wl_registry_bind(d->registry, id, &zxdg_exporter_v2_interface, 1); 1081 1084 } else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) { 1082 1085 d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1); 1083 1086 kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d); ··· 1329 1332 if (data->cursor_shape_manager) { 1330 1333 wp_cursor_shape_manager_v1_destroy(data->cursor_shape_manager); 1331 1334 data->cursor_shape_manager = NULL; 1335 + } 1336 + 1337 + if (data->zxdg_exporter_v2) { 1338 + zxdg_exporter_v2_destroy(data->zxdg_exporter_v2); 1339 + data->zxdg_exporter_v2 = NULL; 1332 1340 } 1333 1341 1334 1342 if (data->kde_output_order) {
+1
src/video/wayland/SDL_waylandvideo.h
··· 79 79 struct wp_viewporter *viewporter; 80 80 struct wp_fractional_scale_manager_v1 *fractional_scale_manager; 81 81 struct zwp_input_timestamps_manager_v1 *input_timestamps_manager; 82 + struct zxdg_exporter_v2 *zxdg_exporter_v2; 82 83 struct kde_output_order_v1 *kde_output_order; 83 84 84 85 struct xkb_context *xkb_context;
+38 -1
src/video/wayland/SDL_waylandwindow.c
··· 38 38 #include "xdg-activation-v1-client-protocol.h" 39 39 #include "viewporter-client-protocol.h" 40 40 #include "fractional-scale-v1-client-protocol.h" 41 + #include "xdg-foreign-unstable-v2-client-protocol.h" 41 42 42 43 #ifdef HAVE_LIBDECOR_H 43 44 #include <libdecor.h> ··· 1484 1485 show_hide_sync_handler 1485 1486 }; 1486 1487 1488 + static void exported_handle_handler(void *data, struct zxdg_exported_v2 *zxdg_exported_v2, const char *handle) 1489 + { 1490 + SDL_WindowData *wind = (SDL_WindowData*)data; 1491 + SDL_PropertiesID props = SDL_GetWindowProperties(wind->sdlwindow); 1492 + 1493 + SDL_free(wind->export_handle); 1494 + wind->export_handle = SDL_strdup(handle); 1495 + 1496 + SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_POINTER, wind->export_handle); 1497 + } 1498 + 1499 + static struct zxdg_exported_v2_listener exported_v2_listener = { 1500 + exported_handle_handler 1501 + }; 1502 + 1487 1503 void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) 1488 1504 { 1489 1505 SDL_VideoData *c = _this->driverdata; ··· 1549 1565 libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, data->app_id); 1550 1566 libdecor_frame_map(data->shell_surface.libdecor.frame); 1551 1567 1568 + if (c->zxdg_exporter_v2) { 1569 + data->exported = zxdg_exporter_v2_export_toplevel(c->zxdg_exporter_v2, data->surface); 1570 + zxdg_exported_v2_add_listener(data->exported, &exported_v2_listener, data); 1571 + } 1572 + 1552 1573 SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame)); 1553 1574 SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame)); 1554 1575 } ··· 1623 1644 data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface); 1624 1645 xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, data->app_id); 1625 1646 xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data); 1647 + 1648 + if (c->zxdg_exporter_v2) { 1649 + data->exported = zxdg_exporter_v2_export_toplevel(c->zxdg_exporter_v2, data->surface); 1650 + zxdg_exported_v2_add_listener(data->exported, &exported_v2_listener, data); 1651 + } 1652 + 1626 1653 SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, data->shell_surface.xdg.roleobj.toplevel); 1627 1654 } 1628 1655 } ··· 1698 1725 #endif 1699 1726 Wayland_SetWindowResizable(_this, window, !!(window->flags & SDL_WINDOW_RESIZABLE)); 1700 1727 Wayland_SetWindowBordered(_this, window, !(window->flags & SDL_WINDOW_BORDERLESS)); 1701 - 1702 1728 1703 1729 /* We're finally done putting the window together, raise if possible */ 1704 1730 if (c->activation_manager) { ··· 1796 1822 if (wind->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP) { 1797 1823 wl_surface_attach(wind->surface, NULL, 0, 0); 1798 1824 wl_surface_commit(wind->surface); 1825 + } 1826 + 1827 + /* Clean up the export handle. */ 1828 + if (wind->exported) { 1829 + zxdg_exported_v2_destroy(wind->exported); 1830 + wind->exported = NULL; 1831 + 1832 + SDL_free(wind->export_handle); 1833 + wind->export_handle = NULL; 1834 + 1835 + SDL_SetProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_POINTER, NULL); 1799 1836 } 1800 1837 1801 1838 #ifdef HAVE_LIBDECOR_H
+2
src/video/wayland/SDL_waylandwindow.h
··· 95 95 struct xdg_activation_token_v1 *activation_token; 96 96 struct wp_viewport *viewport; 97 97 struct wp_fractional_scale_v1 *fractional_scale; 98 + struct zxdg_exported_v2 *exported; 98 99 99 100 SDL_AtomicInt swap_interval_ready; 100 101 ··· 104 105 SDL_Window *keyboard_focus; 105 106 106 107 char *app_id; 108 + char *export_handle; 107 109 float windowed_scale_factor; 108 110 109 111 struct
+200
wayland-protocols/xdg-foreign-unstable-v2.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <protocol name="xdg_foreign_unstable_v2"> 3 + 4 + <copyright> 5 + Copyright © 2015-2016 Red Hat Inc. 6 + 7 + Permission is hereby granted, free of charge, to any person obtaining a 8 + copy of this software and associated documentation files (the "Software"), 9 + to deal in the Software without restriction, including without limitation 10 + the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 + and/or sell copies of the Software, and to permit persons to whom the 12 + Software is furnished to do so, subject to the following conditions: 13 + 14 + The above copyright notice and this permission notice (including the next 15 + paragraph) shall be included in all copies or substantial portions of the 16 + Software. 17 + 18 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 + DEALINGS IN THE SOFTWARE. 25 + </copyright> 26 + 27 + <description summary="Protocol for exporting xdg surface handles"> 28 + This protocol specifies a way for making it possible to reference a surface 29 + of a different client. With such a reference, a client can, by using the 30 + interfaces provided by this protocol, manipulate the relationship between 31 + its own surfaces and the surface of some other client. For example, stack 32 + some of its own surface above the other clients surface. 33 + 34 + In order for a client A to get a reference of a surface of client B, client 35 + B must first export its surface using xdg_exporter.export_toplevel. Upon 36 + doing this, client B will receive a handle (a unique string) that it may 37 + share with client A in some way (for example D-Bus). After client A has 38 + received the handle from client B, it may use xdg_importer.import_toplevel 39 + to create a reference to the surface client B just exported. See the 40 + corresponding requests for details. 41 + 42 + A possible use case for this is out-of-process dialogs. For example when a 43 + sandboxed client without file system access needs the user to select a file 44 + on the file system, given sandbox environment support, it can export its 45 + surface, passing the exported surface handle to an unsandboxed process that 46 + can show a file browser dialog and stack it above the sandboxed client's 47 + surface. 48 + 49 + Warning! The protocol described in this file is experimental and backward 50 + incompatible changes may be made. Backward compatible changes may be added 51 + together with the corresponding interface version bump. Backward 52 + incompatible changes are done by bumping the version number in the protocol 53 + and interface names and resetting the interface version. Once the protocol 54 + is to be declared stable, the 'z' prefix and the version number in the 55 + protocol and interface names are removed and the interface version number is 56 + reset. 57 + </description> 58 + 59 + <interface name="zxdg_exporter_v2" version="1"> 60 + <description summary="interface for exporting surfaces"> 61 + A global interface used for exporting surfaces that can later be imported 62 + using xdg_importer. 63 + </description> 64 + 65 + <request name="destroy" type="destructor"> 66 + <description summary="destroy the xdg_exporter object"> 67 + Notify the compositor that the xdg_exporter object will no longer be 68 + used. 69 + </description> 70 + </request> 71 + 72 + <enum name="error"> 73 + <description summary="error values"> 74 + These errors can be emitted in response to invalid xdg_exporter 75 + requests. 76 + </description> 77 + <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/> 78 + </enum> 79 + 80 + <request name="export_toplevel"> 81 + <description summary="export a toplevel surface"> 82 + The export_toplevel request exports the passed surface so that it can later be 83 + imported via xdg_importer. When called, a new xdg_exported object will 84 + be created and xdg_exported.handle will be sent immediately. See the 85 + corresponding interface and event for details. 86 + 87 + A surface may be exported multiple times, and each exported handle may 88 + be used to create an xdg_imported multiple times. Only xdg_toplevel 89 + equivalent surfaces may be exported, otherwise an invalid_surface 90 + protocol error is sent. 91 + </description> 92 + <arg name="id" type="new_id" interface="zxdg_exported_v2" 93 + summary="the new xdg_exported object"/> 94 + <arg name="surface" type="object" interface="wl_surface" 95 + summary="the surface to export"/> 96 + </request> 97 + </interface> 98 + 99 + <interface name="zxdg_importer_v2" version="1"> 100 + <description summary="interface for importing surfaces"> 101 + A global interface used for importing surfaces exported by xdg_exporter. 102 + With this interface, a client can create a reference to a surface of 103 + another client. 104 + </description> 105 + 106 + <request name="destroy" type="destructor"> 107 + <description summary="destroy the xdg_importer object"> 108 + Notify the compositor that the xdg_importer object will no longer be 109 + used. 110 + </description> 111 + </request> 112 + 113 + <request name="import_toplevel"> 114 + <description summary="import a toplevel surface"> 115 + The import_toplevel request imports a surface from any client given a handle 116 + retrieved by exporting said surface using xdg_exporter.export_toplevel. 117 + When called, a new xdg_imported object will be created. This new object 118 + represents the imported surface, and the importing client can 119 + manipulate its relationship using it. See xdg_imported for details. 120 + </description> 121 + <arg name="id" type="new_id" interface="zxdg_imported_v2" 122 + summary="the new xdg_imported object"/> 123 + <arg name="handle" type="string" 124 + summary="the exported surface handle"/> 125 + </request> 126 + </interface> 127 + 128 + <interface name="zxdg_exported_v2" version="1"> 129 + <description summary="an exported surface handle"> 130 + An xdg_exported object represents an exported reference to a surface. The 131 + exported surface may be referenced as long as the xdg_exported object not 132 + destroyed. Destroying the xdg_exported invalidates any relationship the 133 + importer may have established using xdg_imported. 134 + </description> 135 + 136 + <request name="destroy" type="destructor"> 137 + <description summary="unexport the exported surface"> 138 + Revoke the previously exported surface. This invalidates any 139 + relationship the importer may have set up using the xdg_imported created 140 + given the handle sent via xdg_exported.handle. 141 + </description> 142 + </request> 143 + 144 + <event name="handle"> 145 + <description summary="the exported surface handle"> 146 + The handle event contains the unique handle of this exported surface 147 + reference. It may be shared with any client, which then can use it to 148 + import the surface by calling xdg_importer.import_toplevel. A handle 149 + may be used to import the surface multiple times. 150 + </description> 151 + <arg name="handle" type="string" summary="the exported surface handle"/> 152 + </event> 153 + </interface> 154 + 155 + <interface name="zxdg_imported_v2" version="1"> 156 + <description summary="an imported surface handle"> 157 + An xdg_imported object represents an imported reference to surface exported 158 + by some client. A client can use this interface to manipulate 159 + relationships between its own surfaces and the imported surface. 160 + </description> 161 + 162 + <enum name="error"> 163 + <description summary="error values"> 164 + These errors can be emitted in response to invalid xdg_imported 165 + requests. 166 + </description> 167 + <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/> 168 + </enum> 169 + 170 + <request name="destroy" type="destructor"> 171 + <description summary="destroy the xdg_imported object"> 172 + Notify the compositor that it will no longer use the xdg_imported 173 + object. Any relationship that may have been set up will at this point 174 + be invalidated. 175 + </description> 176 + </request> 177 + 178 + <request name="set_parent_of"> 179 + <description summary="set as the parent of some surface"> 180 + Set the imported surface as the parent of some surface of the client. 181 + The passed surface must be an xdg_toplevel equivalent, otherwise an 182 + invalid_surface protocol error is sent. Calling this function sets up 183 + a surface to surface relation with the same stacking and positioning 184 + semantics as xdg_toplevel.set_parent. 185 + </description> 186 + <arg name="surface" type="object" interface="wl_surface" 187 + summary="the child surface"/> 188 + </request> 189 + 190 + <event name="destroyed"> 191 + <description summary="the imported surface handle has been destroyed"> 192 + The imported surface handle has been destroyed and any relationship set 193 + up has been invalidated. This may happen for various reasons, for 194 + example if the exported surface or the exported surface handle has been 195 + destroyed, if the handle used for importing was invalid. 196 + </description> 197 + </event> 198 + </interface> 199 + 200 + </protocol>