diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 3fb5ca1b6f..dab23d2914 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -894,6 +894,7 @@ void X11_UpdateWindowPosition(SDL_Window *window) Window childReturn, root, parent; Window *children; XWindowAttributes attrs; + int x, y; int dest_x, dest_y; int orig_x, orig_y; Uint64 timeout; @@ -918,8 +919,6 @@ void X11_UpdateWindowPosition(SDL_Window *window) timeout = SDL_GetTicks() + 100; while (SDL_TRUE) { - int x, y; - caught_x11_error = SDL_FALSE; X11_XSync(display, False); X11_XGetWindowAttributes(display, data->xwindow, &attrs); @@ -931,8 +930,6 @@ void X11_UpdateWindowPosition(SDL_Window *window) if (SDL_WINDOW_IS_POPUP(window)) { SDL_GlobalToRelativeForWindow(window, x, y, &x, &y); } - window->x = x; - window->y = y; break; /* window moved, time to go. */ } else if ((x == dest_x) && (y == dest_y)) { break; /* we're at the place we wanted to be anyhow, drop out. */ @@ -946,6 +943,11 @@ void X11_UpdateWindowPosition(SDL_Window *window) SDL_Delay(10); } + if (!caught_x11_error) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height); + } + X11_XSetErrorHandler(prev_handler); caught_x11_error = SDL_FALSE; @@ -1087,8 +1089,6 @@ void X11_SetWindowSize(_THIS, SDL_Window *window) if (!caught_x11_error) { if ((attrs.width != orig_w) || (attrs.height != orig_h)) { - window->w = attrs.width; - window->h = attrs.height; break; /* window changed, time to go. */ } else if ((attrs.width == window->w) && (attrs.height == window->h)) { break; /* we're at the place we wanted to be anyhow, drop out. */ @@ -1097,15 +1097,24 @@ void X11_SetWindowSize(_THIS, SDL_Window *window) if (SDL_GetTicks() >= timeout) { /* Timeout occurred and window size didn't change - * window manager likely denied the resize. */ - window->w = orig_w; - window->h = orig_h; + * window manager likely denied the resize, + * or the new size is the same as the existing: + * - current width: is 'full width'. + * - try to set new width at 'full width + 1', which get truncated to 'full width'. + * - new width is/remains 'full width' + * So, even if we break here as a timeout, we can send an event, since the requested size isn't the same + * as the final size. (even if final size is same as original size). + */ break; } SDL_Delay(10); } + if (!caught_x11_error) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height); + } + X11_XSetErrorHandler(prev_handler); caught_x11_error = SDL_FALSE; } @@ -1455,6 +1464,7 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis Window childReturn, root, parent; Window *children; XWindowAttributes attrs; + int x, y; int orig_w, orig_h, orig_x, orig_y; Uint64 timeout; @@ -1542,7 +1552,6 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis timeout = SDL_GetTicks() + 100; while (SDL_TRUE) { - int x, y; caught_x11_error = SDL_FALSE; X11_XSync(display, False); @@ -1554,14 +1563,12 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis if ((x != orig_x) || (y != orig_y)) { orig_x = x; orig_y = y; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); window_position_changed += 1; } if ((attrs.width != orig_w) || (attrs.height != orig_h)) { orig_w = attrs.width; orig_h = attrs.height; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height); window_size_changed = SDL_TRUE; } @@ -1578,6 +1585,11 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis SDL_Delay(10); } + if (!caught_x11_error) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height); + } + X11_XSetErrorHandler(prev_handler); caught_x11_error = SDL_FALSE; } else { diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 65febaa745..8d16bddaad 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -725,6 +725,37 @@ static int video_getWindowPixelFormat(void *arg) return TEST_COMPLETED; } + +static SDL_bool getPositionFromEvent(int *x, int *y) +{ + SDL_bool ret = SDL_FALSE; + SDL_Event evt; + SDL_zero(evt); + while (SDL_PollEvent(&evt)) { + if (evt.type == SDL_EVENT_WINDOW_MOVED) { + *x = evt.window.data1; + *y = evt.window.data2; + ret = SDL_TRUE; + } + } + return ret; +} + +static SDL_bool getSizeFromEvent(int *w, int *h) +{ + SDL_bool ret = SDL_FALSE; + SDL_Event evt; + SDL_zero(evt); + while (SDL_PollEvent(&evt)) { + if (evt.type == SDL_EVENT_WINDOW_RESIZED) { + *w = evt.window.data1; + *h = evt.window.data2; + ret = SDL_TRUE; + } + } + return ret; +} + /** * \brief Tests call to SDL_GetWindowPosition and SDL_SetWindowPosition * @@ -797,8 +828,23 @@ static int video_getSetWindowPosition(void *arg) currentY = desiredY + 1; SDL_GetWindowPosition(window, ¤tX, ¤tY); SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); - SDLTest_AssertCheck(desiredX == currentX, "Verify returned X position; expected: %d, got: %d", desiredX, currentX); - SDLTest_AssertCheck(desiredY == currentY, "Verify returned Y position; expected: %d, got: %d", desiredY, currentY); + + if (desiredX == currentX && desiredY == currentY) { + SDLTest_AssertCheck(desiredX == currentX, "Verify returned X position; expected: %d, got: %d", desiredX, currentX); + SDLTest_AssertCheck(desiredY == currentY, "Verify returned Y position; expected: %d, got: %d", desiredY, currentY); + } else { + SDL_bool hasEvent; + /* SDL_SetWindowPosition() and SDL_SetWindowSize() will make requests of the window manager and set the internal position and size, + * and then we get events signaling what actually happened, and they get passed on to the application if they're not what we expect. */ + desiredX = currentX + 1; + desiredY = currentY + 1; + hasEvent = getPositionFromEvent(&desiredX, &desiredY); + SDLTest_AssertCheck(hasEvent == SDL_TRUE, "Changing position was not honored by WM, checking present of SDL_EVENT_WINDOW_MOVED"); + if (hasEvent) { + SDLTest_AssertCheck(desiredX == currentX, "Verify returned X position is the position from SDL event; expected: %d, got: %d", desiredX, currentX); + SDLTest_AssertCheck(desiredY == currentY, "Verify returned Y position is the position from SDL event; expected: %d, got: %d", desiredY, currentY); + } + } /* Get position X */ currentX = desiredX + 1; @@ -972,8 +1018,24 @@ static int video_getSetWindowSize(void *arg) currentH = desiredH + 1; SDL_GetWindowSize(window, ¤tW, ¤tH); SDLTest_AssertPass("Call to SDL_GetWindowSize()"); - SDLTest_AssertCheck(desiredW == currentW, "Verify returned width; expected: %d, got: %d", desiredW, currentW); - SDLTest_AssertCheck(desiredH == currentH, "Verify returned height; expected: %d, got: %d", desiredH, currentH); + + if (desiredW == currentW && desiredH == currentH) { + SDLTest_AssertCheck(desiredW == currentW, "Verify returned width; expected: %d, got: %d", desiredW, currentW); + SDLTest_AssertCheck(desiredH == currentH, "Verify returned height; expected: %d, got: %d", desiredH, currentH); + } else { + SDL_bool hasEvent; + /* SDL_SetWindowPosition() and SDL_SetWindowSize() will make requests of the window manager and set the internal position and size, + * and then we get events signaling what actually happened, and they get passed on to the application if they're not what we expect. */ + desiredW = currentW + 1; + desiredH = currentH + 1; + hasEvent = getSizeFromEvent(&desiredW, &desiredH); + SDLTest_AssertCheck(hasEvent == SDL_TRUE, "Changing size was not honored by WM, checking presence of SDL_EVENT_WINDOW_RESIZED"); + if (hasEvent) { + SDLTest_AssertCheck(desiredW == currentW, "Verify returned width is the one from SDL event; expected: %d, got: %d", desiredW, currentW); + SDLTest_AssertCheck(desiredH == currentH, "Verify returned height is the one from SDL event; expected: %d, got: %d", desiredH, currentH); + } + } + /* Get just width */ currentW = desiredW + 1;