wayland: Apply toplevel bounds to windows

Apply the supplied xdg-toplevel bounds to resizable windows during initial mapping. Libdecor functionality will have to be added separately, as the functionality needs to be added to the library first.
This commit is contained in:
Frank Praznik
2025-01-06 16:57:24 -05:00
parent ebe561f916
commit e5a3fcd071
4 changed files with 247 additions and 78 deletions

View File

@@ -849,7 +849,7 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
} else if (SDL_strcmp(interface, "wl_seat") == 0) {
Wayland_display_add_input(d, id, version);
} 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));
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_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);

View File

@@ -538,6 +538,13 @@ static void handle_configure_xdg_toplevel(void *data,
*/
width = wind->floating_width;
height = wind->floating_height;
/* Clamp the window to the toplevel bounds, if any were sent. */
if ((window->flags & SDL_WINDOW_HIDDEN) &&
wind->toplevel_bounds_width && wind->toplevel_bounds_height) {
width = SDL_min(width, wind->toplevel_bounds_width);
height = SDL_min(height, wind->toplevel_bounds_height);
}
}
/* xdg_toplevel spec states that this is a suggestion.
@@ -614,9 +621,28 @@ static void handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_tople
SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
}
static void handle_xdg_toplevel_configure_bounds(void *data,
struct xdg_toplevel *xdg_toplevel,
int32_t width,
int32_t height)
{
SDL_WindowData *window = (SDL_WindowData *)data;
window->toplevel_bounds_width = width;
window->toplevel_bounds_height = height;
}
static void handle_xdg_toplevel_wm_capabilities(void *data,
struct xdg_toplevel *xdg_toplevel,
struct wl_array *capabilities)
{
/* NOP */
}
static const struct xdg_toplevel_listener toplevel_listener_xdg = {
handle_configure_xdg_toplevel,
handle_close_xdg_toplevel
handle_close_xdg_toplevel,
handle_xdg_toplevel_configure_bounds,
handle_xdg_toplevel_wm_capabilities
};
static void handle_configure_xdg_popup(void *data,
@@ -1358,6 +1384,12 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
} else
#endif
if (c->shell.xdg) {
/* Create the window decorations */
if (data->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP && data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
zxdg_toplevel_decoration_v1_add_listener(data->server_decoration, &decoration_listener, window);
}
/* Unlike libdecor we need to call this explicitly to prevent a deadlock.
* libdecor will call this as part of their configure event!
* -flibit
@@ -1369,14 +1401,6 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
WAYLAND_wl_display_dispatch(c->display);
}
}
/* Create the window decorations */
if (data->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP && data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
zxdg_toplevel_decoration_v1_add_listener(data->server_decoration,
&decoration_listener,
window);
}
} else {
/* Nothing to see here, just commit. */
wl_surface_commit(data->surface);

View File

@@ -114,13 +114,15 @@ typedef struct
int window_width, window_height;
int system_min_required_width;
int system_min_required_height;
int toplevel_bounds_width;
int toplevel_bounds_height;
SDL_bool needs_resize_event;
SDL_bool floating_resize_pending;
SDL_bool was_floating;
SDL_bool is_fullscreen;
SDL_bool in_fullscreen_transition;
Uint32 fullscreen_flags;
SDL_bool double_buffer;
SDL_bool double_buffer;
} SDL_WindowData;
extern void Wayland_ShowWindow(_THIS, SDL_Window *window);