Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x11: Don't force position windows with an undefined position #12068

Merged
merged 1 commit into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 11 additions & 35 deletions src/video/x11/SDL_x11events.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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 &&
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
30 changes: 9 additions & 21 deletions src/video/x11/SDL_x11window.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 6 additions & 1 deletion src/video/x11/SDL_x11window.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading