This commit is contained in:
Vladimir Serbinenko 2025-06-22 18:11:55 +08:00 committed by GitHub
commit 3dadb694de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 117 additions and 1 deletions

View File

@ -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 */

View File

@ -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)

View File

@ -543,6 +543,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;
@ -568,6 +572,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;

View File

@ -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)

View File

@ -847,6 +847,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, 5));
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) {
@ -1098,6 +1100,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;

View File

@ -64,6 +64,7 @@ typedef struct
struct
{
struct xdg_wm_base *xdg;
struct wl_shell *wl;
#ifdef HAVE_LIBDECOR_H
struct libdecor *libdecor;
#endif

View File

@ -385,6 +385,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);
}
}
}
@ -480,6 +494,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;
@ -1359,6 +1429,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
SetMinMaxDimensions(window, SDL_FALSE);
}
} 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 */
@ -1532,6 +1607,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;
}
}
/*
@ -1812,6 +1892,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);
@ -1891,6 +1976,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);
@ -2205,6 +2295,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);

View File

@ -68,6 +68,7 @@ typedef struct
} roleobj;
SDL_bool initial_configure_seen;
} xdg;
struct wl_shell_surface *wl;
} shell_surface;
enum
{