x11: Catch X11 errors in X11_SetWindowPosition and X11_SetWindowSize.
The functions can go south if other operations are in progress, like X11_SetWindowBordered, which might be doing something traumatic behind the scenes of the window manager. We can't make these tasks totally synchronous, which would fix the problem, because not only can the window manager block however long it wants, it might also decide to deny our requests without any notification, so we'd be waiting forever for a window change that isn't coming. :( Fixes #5274.main
parent
3425e9950e
commit
7e15ad2fc4
|
@ -782,11 +782,22 @@ X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
|
||||||
X11_XFlush(display);
|
X11_XFlush(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDL_bool caught_x11_error = SDL_FALSE;
|
||||||
|
static int
|
||||||
|
X11_CatchAnyError(Display * d, XErrorEvent * e)
|
||||||
|
{
|
||||||
|
/* this may happen during tumultuous times when we are polling anyhow,
|
||||||
|
so just note we had an error and return control. */
|
||||||
|
caught_x11_error = SDL_TRUE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
X11_SetWindowPosition(_THIS, SDL_Window * window)
|
X11_SetWindowPosition(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||||
Display *display = data->videodata->display;
|
Display *display = data->videodata->display;
|
||||||
|
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
|
||||||
unsigned int childCount;
|
unsigned int childCount;
|
||||||
Window childReturn, root, parent;
|
Window childReturn, root, parent;
|
||||||
Window* children;
|
Window* children;
|
||||||
|
@ -805,14 +816,20 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
|
||||||
|
|
||||||
/* Wait a brief time to see if the window manager decided to let this move happen.
|
/* Wait a brief time to see if the window manager decided to let this move happen.
|
||||||
If the window changes at all, even to an unexpected value, we break out. */
|
If the window changes at all, even to an unexpected value, we break out. */
|
||||||
|
X11_XSync(display, False);
|
||||||
|
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
|
||||||
|
|
||||||
timeout = SDL_GetTicks() + 100;
|
timeout = SDL_GetTicks() + 100;
|
||||||
while (SDL_TRUE) {
|
while (SDL_TRUE) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
caught_x11_error = SDL_FALSE;
|
||||||
X11_XSync(display, False);
|
X11_XSync(display, False);
|
||||||
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||||
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
|
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
|
||||||
attrs.x, attrs.y, &x, &y, &childReturn);
|
attrs.x, attrs.y, &x, &y, &childReturn);
|
||||||
|
|
||||||
|
if (!caught_x11_error) {
|
||||||
if ((x != orig_x) || (y != orig_y)) {
|
if ((x != orig_x) || (y != orig_y)) {
|
||||||
window->x = x;
|
window->x = x;
|
||||||
window->y = y;
|
window->y = y;
|
||||||
|
@ -820,6 +837,7 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
|
||||||
} else if ((x == window->x) && (y == window->y)) {
|
} else if ((x == window->x) && (y == window->y)) {
|
||||||
break; /* we're at the place we wanted to be anyhow, drop out. */
|
break; /* we're at the place we wanted to be anyhow, drop out. */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
||||||
break;
|
break;
|
||||||
|
@ -827,6 +845,9 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
|
||||||
|
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X11_XSetErrorHandler(prev_handler);
|
||||||
|
caught_x11_error = SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -892,6 +913,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||||
Display *display = data->videodata->display;
|
Display *display = data->videodata->display;
|
||||||
|
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
|
||||||
XWindowAttributes attrs;
|
XWindowAttributes attrs;
|
||||||
int orig_w, orig_h;
|
int orig_w, orig_h;
|
||||||
Uint32 timeout;
|
Uint32 timeout;
|
||||||
|
@ -943,13 +965,18 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
||||||
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
|
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X11_XSync(display, False);
|
||||||
|
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
|
||||||
|
|
||||||
/* Wait a brief time to see if the window manager decided to let this resize happen.
|
/* Wait a brief time to see if the window manager decided to let this resize happen.
|
||||||
If the window changes at all, even to an unexpected value, we break out. */
|
If the window changes at all, even to an unexpected value, we break out. */
|
||||||
timeout = SDL_GetTicks() + 100;
|
timeout = SDL_GetTicks() + 100;
|
||||||
while (SDL_TRUE) {
|
while (SDL_TRUE) {
|
||||||
|
caught_x11_error = SDL_FALSE;
|
||||||
X11_XSync(display, False);
|
X11_XSync(display, False);
|
||||||
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||||
|
|
||||||
|
if (!caught_x11_error) {
|
||||||
if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
|
if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
|
||||||
window->w = attrs.width;
|
window->w = attrs.width;
|
||||||
window->h = attrs.height;
|
window->h = attrs.height;
|
||||||
|
@ -957,6 +984,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
||||||
} else if ((attrs.width == window->w) && (attrs.height == window->h)) {
|
} else if ((attrs.width == window->w) && (attrs.height == window->h)) {
|
||||||
break; /* we're at the place we wanted to be anyhow, drop out. */
|
break; /* we're at the place we wanted to be anyhow, drop out. */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
||||||
break;
|
break;
|
||||||
|
@ -964,6 +992,9 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
||||||
|
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X11_XSetErrorHandler(prev_handler);
|
||||||
|
caught_x11_error = SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue