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.
This commit is contained in:
Frank Praznik
2025-01-22 19:18:56 -05:00
parent 72a3eae0da
commit d0ae093681
3 changed files with 26 additions and 57 deletions

View File

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

View File

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

View File

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