From 4562da622c830c87659af7cd8bd8da486289de84 Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Mon, 2 Aug 2021 16:40:56 -0400
Subject: [PATCH] wayland: Make libdecor configure match xdg_toplevel
---
src/video/wayland/SDL_waylandwindow.c | 91 +++++++++++++++++----------
1 file changed, 57 insertions(+), 34 deletions(-)
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 5940f0b7c..dff4a0687 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -262,6 +262,7 @@ handle_configure_xdg_toplevel(void *data,
wind->floating_height = height;
}
+ /* Store this now so the xdg_surface configure knows what to resize to */
window->w = width;
window->h = height;
}
@@ -284,69 +285,91 @@ decoration_frame_configure(struct libdecor_frame *frame,
struct libdecor_configuration *configuration,
void *user_data)
{
- SDL_WindowData *wind = user_data;
+ SDL_WindowData *wind = (SDL_WindowData *)user_data;
SDL_Window *window = wind->sdlwindow;
- int width, height;
- enum libdecor_window_state window_state;
struct libdecor_state *state;
- /* window size */
- if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
- width = window->w;
- height = window->h;
- }
-
- Wayland_HandleResize(window, width, height, wind->scale_factor);
- wind->shell_surface.libdecor.initial_configure_seen = SDL_TRUE;
+ enum libdecor_window_state window_state;
+ int width, height;
- /* window state */
- if (!libdecor_configuration_get_window_state(configuration, &window_state)) {
- window_state = LIBDECOR_WINDOW_STATE_NONE;
+ SDL_bool focused = SDL_FALSE;
+ SDL_bool fullscreen = SDL_FALSE;
+ SDL_bool maximized = SDL_FALSE;
+ SDL_bool tiled = SDL_FALSE;
+ SDL_bool floating;
+
+ static const enum libdecor_window_state tiled_states = (
+ LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT |
+ LIBDECOR_WINDOW_STATE_TILED_TOP | LIBDECOR_WINDOW_STATE_TILED_BOTTOM
+ );
+
+ /* Window State */
+ if (libdecor_configuration_get_window_state(configuration, &window_state)) {
+ fullscreen = (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
+ maximized = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
+ focused = (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
+ tiled = (window_state & tiled_states) != 0;
}
+ floating = !(fullscreen || maximized || tiled);
- /* Always send maximized/restored/focus events; if the event is redundant it will
- * automatically be discarded (see src/events/SDL_windowevents.c).
- *
- * No, we do not get minimize events from libdecor.
- */
- if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) {
- window->flags |= SDL_WINDOW_FULLSCREEN;
- } else {
+ if (!fullscreen) {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
/* We might need to re-enter fullscreen after being restored from minimized */
SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
- } else {
+ fullscreen = SDL_TRUE;
+ }
+
+ /* Always send a maximized/restore event; if the event is redundant it will
+ * automatically be discarded (see src/events/SDL_windowevents.c)
+ *
+ * No, we do not get minimize events from libdecor.
+ */
+ if (!fullscreen) {
SDL_SendWindowEvent(window,
- (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ?
+ maximized ?
SDL_WINDOWEVENT_MAXIMIZED :
SDL_WINDOWEVENT_RESTORED,
0, 0);
}
- window->flags &= ~SDL_WINDOW_FULLSCREEN;
}
+ /* Similar to maximized/restore events above, send focus events too! */
SDL_SendWindowEvent(window,
- (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) ?
+ focused ?
SDL_WINDOWEVENT_FOCUS_GAINED :
SDL_WINDOWEVENT_FOCUS_LOST,
0, 0);
- /* commit frame state */
- state = libdecor_state_new(width, height);
- libdecor_frame_commit(frame, state, configuration);
- libdecor_state_free(state);
-
- /* store floating dimensions */
- if (libdecor_frame_is_floating(frame)) {
+ /* This will never set 0 for width/height unless the function returns false */
+ if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
+ if (floating) {
+ width = wind->floating_width;
+ height = wind->floating_height;
+ } else {
+ width = window->w;
+ height = window->h;
+ }
+ } else if (floating) {
+ /* store current floating dimensions for restoring */
wind->floating_width = width;
wind->floating_height = height;
}
+ /* Do the resize on the SDL side (this will set window->w/h)... */
+ Wayland_HandleResize(window, width, height, wind->scale_factor);
+ wind->shell_surface.libdecor.initial_configure_seen = SDL_TRUE;
+
+ /* ... then commit the changes on the libdecor side. */
+ state = libdecor_state_new(width, height);
+ libdecor_frame_commit(frame, state, configuration);
+ libdecor_state_free(state);
+
/* Update the resize capability. Since this will change the capabilities and
* commit a new frame state with the last known content dimension, this has
* to be called after the new state has been commited and the new content
- * dimensions were updated. */
+ * dimensions were updated.
+ */
Wayland_SetWindowResizable(SDL_GetVideoDevice(), window,
window->flags & SDL_WINDOW_RESIZABLE);
}