wayland: Make libdecor configure match xdg_toplevel
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
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 5940f0b..dff4a06 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);
}