From d0ae0936811a49289d7ac0be49058ff9e897156b Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Wed, 22 Jan 2025 19:18:56 -0500
Subject: [PATCH] x11: Don't force position windows with an undefined position
An undefined position means that the window manager can handle placement, so SDL shouldn't override that by forcing a position when showing a window.
Allows for removing a fair bit of now-unnecessary code as well.
---
src/video/x11/SDL_x11events.c | 46 +++++++++--------------------------
src/video/x11/SDL_x11window.c | 30 +++++++----------------
src/video/x11/SDL_x11window.h | 7 +++++-
3 files changed, 26 insertions(+), 57 deletions(-)
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 0ced1b68d3074..aebed3ef0710c 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -1424,7 +1424,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
if (xevent->xconfigure.x != data->last_xconfigure.x ||
xevent->xconfigure.y != data->last_xconfigure.y) {
- if (!data->disable_size_position_events) {
+ if (!data->size_move_event_flags) {
SDL_Window *w;
int x = xevent->xconfigure.x;
int y = xevent->xconfigure.y;
@@ -1448,7 +1448,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
if (xevent->xconfigure.width != data->last_xconfigure.width ||
xevent->xconfigure.height != data->last_xconfigure.height) {
- if (!data->disable_size_position_events) {
+ if (!data->size_move_event_flags) {
data->pending_operation &= ~X11_PENDING_OP_RESIZE;
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED,
xevent->xconfigure.width,
@@ -1799,7 +1799,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
* shut off to avoid bogus window sizes and positions, and
* note that the old borders were non-zero for restoration.
*/
- data->disable_size_position_events = true;
+ data->size_move_event_flags |= X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS;
data->previous_borders_nonzero = true;
} else if (!(flags & SDL_WINDOW_FULLSCREEN) &&
data->previous_borders_nonzero &&
@@ -1809,10 +1809,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
* off size events until the borders come back to avoid bogus
* window sizes and positions.
*/
- data->disable_size_position_events = true;
+ data->size_move_event_flags |= X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS;
data->previous_borders_nonzero = false;
} else {
- data->disable_size_position_events = false;
+ data->size_move_event_flags = 0;
data->previous_borders_nonzero = false;
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) {
@@ -1845,7 +1845,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
data->pending_operation |= X11_PENDING_OP_MOVE;
data->expected.x = data->window->pending.x - data->border_left;
data->expected.y = data->window->pending.y - data->border_top;
- X11_XMoveWindow(display, data->xwindow, data->window->pending.x - data->border_left, data->window->pending.y - data->border_top);
+ X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y);
}
if (data->pending_size) {
data->pending_size = false;
@@ -1875,37 +1875,13 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
right approach, but it seems to work. */
X11_UpdateKeymap(_this, true);
} else if (xevent->xproperty.atom == videodata->atoms._NET_FRAME_EXTENTS) {
- if (data->disable_size_position_events) {
- /* Re-enable size events if they were turned off waiting for the borders to come back
- * when leaving fullscreen.
- */
- data->disable_size_position_events = false;
+ /* Events are disabled when leaving fullscreen until the borders appear to avoid
+ * incorrect size/position events.
+ */
+ if (data->size_move_event_flags) {
+ data->size_move_event_flags &= ~X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS;
X11_GetBorderValues(data);
- if (data->border_top != 0 || data->border_left != 0 || data->border_right != 0 || data->border_bottom != 0) {
- // Adjust if the window size/position changed to accommodate the borders.
- data->pending_operation |= X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE;
-
- if (data->pending_position) {
- data->pending_position = false;
- data->expected.x = data->window->pending.x - data->border_left;
- data->expected.y = data->window->pending.y - data->border_top;
-
- } else {
- data->expected.x = data->window->windowed.x - data->border_left;
- data->expected.y = data->window->windowed.y - data->border_top;
- }
- if (data->pending_size) {
- data->pending_size = false;
- data->expected.w = data->window->pending.w;
- data->expected.h = data->window->pending.h;
- } else {
- data->expected.w = data->window->windowed.w;
- data->expected.h = data->window->windowed.h;
- }
- X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y - data->border_top);
- X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h);
- }
}
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) {
data->toggle_borders = false;
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 0ecabec6752dc..c3c125eafeb20 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -1440,9 +1440,6 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
X11_UpdateWindowPosition(window, false);
}
- const int target_x = window->last_position_pending ? window->pending.x : window->x;
- const int target_y = window->last_position_pending ? window->pending.y : window->y;
-
/* Whether XMapRaised focuses the window is based on the window type and it is
* wm specific. There isn't much we can do here */
(void)bActivate;
@@ -1475,33 +1472,24 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
X11_GetBorderValues(data);
}
- /* Some window managers can send garbage coordinates while mapping the window, and need the position sent again
- * after mapping or the window may not be positioned properly.
- *
- * Don't emit size and position events during the initial configure events, they will be sent afterwards, when the
- * final coordinates are available to avoid sending garbage values.
+ // Apply the pending position, if any, after the window is mapped.
+ data->pending_position = window->last_position_pending;
+
+ /* Some window managers can send garbage coordinates while mapping the window, so don't emit size and position
+ * events during the initial configure events.
*/
- data->disable_size_position_events = true;
+ data->size_move_event_flags = X11_SIZE_MOVE_EVENTS_DISABLE;
X11_XSync(display, False);
X11_PumpEvents(_this);
+ data->size_move_event_flags = 0;
// If a configure event was received (type is non-zero), send the final window size and coordinates.
if (data->last_xconfigure.type) {
- int x = data->last_xconfigure.x;
- int y = data->last_xconfigure.y;
- SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
-
- // If the borders appeared, this happened automatically in the event system, otherwise, set the position now.
- if (data->disable_size_position_events && (target_x != x || target_y != y)) {
- data->pending_operation = X11_PENDING_OP_MOVE;
- X11_XMoveWindow(display, data->xwindow, target_x, target_y);
- }
-
+ int x, y;
+ SDL_GlobalToRelativeForWindow(data->window, data->last_xconfigure.x, data->last_xconfigure.y, &x, &y);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, data->last_xconfigure.width, data->last_xconfigure.height);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y);
}
-
- data->disable_size_position_events = false;
}
void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h
index 16936033596f2..f1a73ab592480 100644
--- a/src/video/x11/SDL_x11window.h
+++ b/src/video/x11/SDL_x11window.h
@@ -103,10 +103,15 @@ struct SDL_WindowData
X11_PENDING_OP_RESIZE = 0x20
} pending_operation;
+ enum
+ {
+ X11_SIZE_MOVE_EVENTS_DISABLE = 0x01, // Events are completely disabled.
+ X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS = 0x02, // Events are disabled until a _NET_FRAME_EXTENTS event arrives.
+ } size_move_event_flags;
+
bool pending_size;
bool pending_position;
bool window_was_maximized;
- bool disable_size_position_events;
bool previous_borders_nonzero;
bool toggle_borders;
bool fullscreen_borders_forced_on;