1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matti=20Lehtim=C3=A4ki?= <matti.lehtimaki@jolla.com>
Date: Wed, 20 Apr 2022 18:03:42 +0300
Subject: [PATCH] wayland: Bring back wl_shell support
---
include/SDL_syswm.h | 2 +-
src/video/wayland/SDL_waylanddyn.h | 2 +
src/video/wayland/SDL_waylandevents.c | 8 +++
src/video/wayland/SDL_waylandsym.h | 2 +
src/video/wayland/SDL_waylandvideo.c | 7 ++
src/video/wayland/SDL_waylandvideo.h | 1 +
src/video/wayland/SDL_waylandwindow.c | 95 +++++++++++++++++++++++++++
src/video/wayland/SDL_waylandwindow.h | 1 +
8 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h
index 7b8bd6ef996571bbba2e5f1e139a0c9292c88146..671a26ee945bdac99de9f07b57aef9cc893f4cec 100644
--- a/include/SDL_syswm.h
+++ b/include/SDL_syswm.h
@@ -294,7 +294,7 @@ struct SDL_SysWMinfo
{
struct wl_display *display; /**< Wayland display */
struct wl_surface *surface; /**< Wayland surface */
- void *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
+ struct wl_shell_surface *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */
struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */
struct xdg_toplevel *xdg_toplevel; /**< Wayland xdg toplevel role */
diff --git a/src/video/wayland/SDL_waylanddyn.h b/src/video/wayland/SDL_waylanddyn.h
index 6feb343912b15a6a9360a11b66a08c0c4e36f882..2c93149cd2dcbff5a69c20606c028aa13905dced 100644
--- a/src/video/wayland/SDL_waylanddyn.h
+++ b/src/video/wayland/SDL_waylanddyn.h
@@ -111,11 +111,13 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define wl_shm_pool_interface (*WAYLAND_wl_shm_pool_interface)
#define wl_buffer_interface (*WAYLAND_wl_buffer_interface)
#define wl_registry_interface (*WAYLAND_wl_registry_interface)
+#define wl_shell_surface_interface (*WAYLAND_wl_shell_surface_interface)
#define wl_region_interface (*WAYLAND_wl_region_interface)
#define wl_pointer_interface (*WAYLAND_wl_pointer_interface)
#define wl_keyboard_interface (*WAYLAND_wl_keyboard_interface)
#define wl_compositor_interface (*WAYLAND_wl_compositor_interface)
#define wl_output_interface (*WAYLAND_wl_output_interface)
+#define wl_shell_interface (*WAYLAND_wl_shell_interface)
#define wl_shm_interface (*WAYLAND_wl_shm_interface)
#define wl_data_device_interface (*WAYLAND_wl_data_device_interface)
#define wl_data_offer_interface (*WAYLAND_wl_data_offer_interface)
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index a8382812ab149c4377441d46a693f736f5430cad..45d679abdafb94708e478745d4f1db57922c37b7 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -518,6 +518,10 @@ static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
input->seat,
serial);
}
+ } else {
+ if (window_data->shell_surface.wl) {
+ wl_shell_surface_move(window_data->shell_surface.wl, input->seat, serial);
+ }
}
return SDL_TRUE;
@@ -543,6 +547,10 @@ static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
serial,
directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
+ } else {
+ if (window_data->shell_surface.wl) {
+ wl_shell_surface_resize(window_data->shell_surface.wl, input->seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+ }
}
return SDL_TRUE;
diff --git a/src/video/wayland/SDL_waylandsym.h b/src/video/wayland/SDL_waylandsym.h
index 1b02b01c6691bd2df30508ab88bbd990586594d0..27ff34a31a77c970300790697204594d24e11a1f 100644
--- a/src/video/wayland/SDL_waylandsym.h
+++ b/src/video/wayland/SDL_waylandsym.h
@@ -101,11 +101,13 @@ SDL_WAYLAND_INTERFACE(wl_surface_interface)
SDL_WAYLAND_INTERFACE(wl_shm_pool_interface)
SDL_WAYLAND_INTERFACE(wl_buffer_interface)
SDL_WAYLAND_INTERFACE(wl_registry_interface)
+SDL_WAYLAND_INTERFACE(wl_shell_surface_interface)
SDL_WAYLAND_INTERFACE(wl_region_interface)
SDL_WAYLAND_INTERFACE(wl_pointer_interface)
SDL_WAYLAND_INTERFACE(wl_keyboard_interface)
SDL_WAYLAND_INTERFACE(wl_compositor_interface)
SDL_WAYLAND_INTERFACE(wl_output_interface)
+SDL_WAYLAND_INTERFACE(wl_shell_interface)
SDL_WAYLAND_INTERFACE(wl_shm_interface)
SDL_WAYLAND_INTERFACE(wl_data_device_interface)
SDL_WAYLAND_INTERFACE(wl_data_source_interface)
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 2cae471792cd692129f193fac2100d7d98ab6705..70e9d7306a8fcc60a4b8b1a9289c18f88a8de990 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -846,6 +846,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
} else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 3));
xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
+ } else if (SDL_strcmp(interface, "wl_shell") == 0) {
+ d->shell.wl = wl_registry_bind(d->registry, id, &wl_shell_interface, 1);
} else if (SDL_strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
} else if (SDL_strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
@@ -1097,6 +1099,11 @@ static void Wayland_VideoCleanup(_THIS)
data->shm = NULL;
}
+ if (data->shell.wl) {
+ wl_shell_destroy(data->shell.wl);
+ data->shell.wl = NULL;
+ }
+
if (data->shell.xdg) {
xdg_wm_base_destroy(data->shell.xdg);
data->shell.xdg = NULL;
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index b7b3348c6d4d9285971d5a2416f7d123f303c7f8..e57ab2bd21a3064c257d704b4912c22d5c49074e 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -64,6 +64,7 @@ typedef struct
struct
{
struct xdg_wm_base *xdg;
+ struct wl_shell *wl;
#ifdef HAVE_LIBDECOR_H
struct libdecor *libdecor;
#endif
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 08df3638c2e795ecdf4cd5f4972bd5d4f866653d..4cb20afbda9aef1edad59b3cf2bd73a7f6e3d289 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -446,6 +446,20 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output)
} else {
xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
}
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can't do anything yet, wait for ShowWindow */
+ }
+
+ wl_surface_commit(wind->surface);
+
+ if (output) {
+ wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ 0, output);
+ } else {
+ wl_shell_surface_set_toplevel(wind->shell_surface.wl);
+ }
}
}
@@ -541,6 +555,62 @@ static const struct wl_callback_listener gles_swap_frame_listener = {
static void Wayland_HandleResize(SDL_Window *window, int width, int height, float scale);
+/* On modern desktops, we probably will use the xdg-shell protocol instead
+ of wl_shell, but wl_shell might be useful on older Wayland installs that
+ don't have the newer protocol, or embedded things that don't have a full
+ window manager. */
+
+static void
+handle_ping_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
+ uint32_t serial)
+{
+ wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+handle_configure_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
+ uint32_t edges, int32_t width, int32_t height)
+{
+ SDL_WindowData *wind = (SDL_WindowData *)data;
+ SDL_Window *window = wind->sdlwindow;
+
+ /* wl_shell_surface spec states that this is a suggestion.
+ Ignore if less than or greater than max/min size. */
+
+ if (width == 0 || height == 0) {
+ return;
+ }
+
+ if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
+ if ((window->flags & SDL_WINDOW_RESIZABLE)) {
+ if (window->max_w > 0) {
+ width = SDL_min(width, window->max_w);
+ }
+ width = SDL_max(width, window->min_w);
+
+ if (window->max_h > 0) {
+ height = SDL_min(height, window->max_h);
+ }
+ height = SDL_max(height, window->min_h);
+ } else {
+ return;
+ }
+ }
+
+ Wayland_HandleResize(window, width, height, wind->scale_factor);
+}
+
+static void
+handle_popup_done_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener_wl = {
+ handle_ping_wl_shell_surface,
+ handle_configure_wl_shell_surface,
+ handle_popup_done_wl_shell_surface
+};
+
static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
{
SDL_WindowData *wind = (SDL_WindowData *)data;
@@ -1374,6 +1444,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
}
+ } else {
+ data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface);
+ wl_shell_surface_set_class(data->shell_surface.wl, c->classname);
+ wl_shell_surface_set_user_data(data->shell_surface.wl, data);
+ wl_shell_surface_add_listener(data->shell_surface.wl, &shell_surface_listener_wl, data);
}
/* Restore state that was set prior to this call */
@@ -1549,6 +1624,11 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
xdg_surface_destroy(wind->shell_surface.xdg.surface);
wind->shell_surface.xdg.surface = NULL;
}
+ } else {
+ if (wind->shell_surface.wl) {
+ wl_shell_surface_destroy(wind->shell_surface.wl);
+ wind->shell_surface.wl = NULL;
+ }
}
/*
@@ -1829,6 +1909,11 @@ void Wayland_RestoreWindow(_THIS, SDL_Window *window)
return; /* Can't do anything yet, wait for ShowWindow */
}
xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel);
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can't do anything yet, wait for ShowWindow */
+ }
+ wl_shell_surface_set_toplevel(wind->shell_surface.wl);
}
WAYLAND_wl_display_roundtrip(viddata->display);
@@ -1908,6 +1993,11 @@ void Wayland_MaximizeWindow(_THIS, SDL_Window *window)
return; /* Can't do anything yet, wait for ShowWindow */
}
xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can't do anything yet, wait for ShowWindow */
+ }
+ wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
}
WAYLAND_wl_display_roundtrip(viddata->display);
@@ -2209,6 +2299,11 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window *window)
return; /* Can't do anything yet, wait for ShowWindow */
}
xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, title);
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can'd do anything yet, wait for ShowWindow */
+ }
+ wl_shell_surface_set_title(wind->shell_surface.wl, title);
}
WAYLAND_wl_display_flush(viddata->display);
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 36600a4d2783e5205d0e1d2faf8422b54e1f7848..0951126949879d863cde175684a3605367428824 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -67,6 +67,7 @@ typedef struct
} roleobj;
SDL_bool initial_configure_seen;
} xdg;
+ struct wl_shell_surface *wl;
} shell_surface;
enum
{
|