From f8e8dff7eecb0626fcd7b2ae097833fadb5cb7c1 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 23 Jul 2023 11:25:15 -0400 Subject: [PATCH] tests: Fix automated window grab and positioning tests under Wayland/XWayland When using the Wayland video driver or X11 under XWayland, create a renderer and present a frame as part of window creation, as Wayland requires that a frame be presented for the window to be fully mapped and displayed onscreen. This fixes the grab and expected window size tests. This also disables the window positioning tests when running under the Wayland driver, as Wayland does not allow application windows to position themselves in the desktop space, which renders the tests unreliable and subject to spurious failure. --- test/testautomation_video.c | 111 ++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 12 deletions(-) diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 8300b2cee..b57fb8213 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -15,6 +15,7 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) SDL_Window *window; int w, h; SDL_WindowFlags flags; + SDL_bool needs_renderer = SDL_FALSE; /* Standard window */ w = SDLTest_RandomIntegerInRange(320, 1024); @@ -25,6 +26,35 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d)", w, h, flags); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); + /* Wayland and XWayland windows require that a frame be presented before they are fully mapped and visible onscreen. + * This is required for the mouse/keyboard grab tests to pass. + */ + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { + needs_renderer = SDL_TRUE; + } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + /* Try to detect if the x11 driver is running under XWayland */ + const char *session_type = SDL_getenv("XDG_SESSION_TYPE"); + if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) { + needs_renderer = SDL_TRUE; + } + } + + if (needs_renderer) { + SDL_Renderer *renderer = SDL_CreateRenderer(window, NULL, 0); + if (renderer) { + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + + /* Some desktops don't display the window immediately after presentation, + * so delay to give the window time to actually appear on the desktop. + */ + SDL_Delay(100); + } else { + SDLTest_Log("Unable to create a renderer, some tests may fail on Wayland/XWayland"); + } + } + return window; } @@ -1629,6 +1659,11 @@ cleanup: * * Especially useful when run on a multi-monitor system with different DPI scales per monitor, * to test that the window size is maintained when moving between monitors. + * + * As the Wayland windowing protocol does not allow application windows to control their position in the + * desktop space, coupled with the general asynchronous nature of Wayland compositors, the positioning + * tests don't work in windowed mode and are unreliable in fullscreen mode, thus are disabled when using + * the Wayland video driver. All that can be done is check that the windows are the expected size. */ static int video_setWindowCenteredOnDisplay(void *arg) { @@ -1640,6 +1675,7 @@ static int video_setWindowCenteredOnDisplay(void *arg) int displayNum; int result; SDL_Rect display0, display1; + SDL_bool video_driver_is_wayland = SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0; displays = SDL_GetDisplays(&displayNum); if (displays) { @@ -1682,18 +1718,45 @@ static int video_setWindowCenteredOnDisplay(void *arg) SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); + /* Wayland windows require that a frame be presented before they are fully mapped and visible onscreen. */ + if (video_driver_is_wayland) { + SDL_Renderer *renderer = SDL_CreateRenderer(window, NULL, 0); + + if (renderer) { + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + + /* Some desktops don't display the window immediately after presentation, + * so delay to give the window time to actually appear on the desktop. + */ + SDL_Delay(100); + } else { + SDLTest_Log("Unable to create a renderer, tests may fail under Wayland"); + } + } + /* Check the window is centered on the requested display */ currentDisplay = SDL_GetDisplayForWindow(window); SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display ID (current: %d, expected: %d)", currentDisplay, expectedDisplay); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display ID (current: %d, expected: %d)", currentDisplay, expectedDisplay); + } else { + SDLTest_Log("Skipping display ID validation: Wayland driver does not support window positioning"); + } SDLTest_AssertCheck(currentW == w, "Validate width (current: %d, expected: %d)", currentW, w); SDLTest_AssertCheck(currentH == h, "Validate height (current: %d, expected: %d)", currentH, h); - SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); - SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); + SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); + } else { + SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); + } /* Enter fullscreen desktop */ + SDL_SetWindowPosition(window, x, y); result = SDL_SetWindowFullscreen(window, SDL_TRUE); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); @@ -1702,11 +1765,19 @@ static int video_setWindowCenteredOnDisplay(void *arg) SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display ID (current: %d, expected: %d)", currentDisplay, expectedDisplay); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display ID (current: %d, expected: %d)", currentDisplay, expectedDisplay); + } else { + SDLTest_Log("Skipping display ID validation: Wayland driver does not support window positioning"); + } SDLTest_AssertCheck(currentW == expectedDisplayRect.w, "Validate width (current: %d, expected: %d)", currentW, expectedDisplayRect.w); SDLTest_AssertCheck(currentH == expectedDisplayRect.h, "Validate height (current: %d, expected: %d)", currentH, expectedDisplayRect.h); - SDLTest_AssertCheck(currentX == expectedDisplayRect.x, "Validate x (current: %d, expected: %d)", currentX, expectedDisplayRect.x); - SDLTest_AssertCheck(currentY == expectedDisplayRect.y, "Validate y (current: %d, expected: %d)", currentY, expectedDisplayRect.y); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentX == expectedDisplayRect.x, "Validate x (current: %d, expected: %d)", currentX, expectedDisplayRect.x); + SDLTest_AssertCheck(currentY == expectedDisplayRect.y, "Validate y (current: %d, expected: %d)", currentY, expectedDisplayRect.y); + } else { + SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); + } /* Leave fullscreen desktop */ result = SDL_SetWindowFullscreen(window, SDL_FALSE); @@ -1717,11 +1788,19 @@ static int video_setWindowCenteredOnDisplay(void *arg) SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); + } else { + SDLTest_Log("Skipping display ID validation: Wayland driver does not support window positioning"); + } SDLTest_AssertCheck(currentW == w, "Validate width (current: %d, expected: %d)", currentW, w); SDLTest_AssertCheck(currentH == h, "Validate height (current: %d, expected: %d)", currentH, h); - SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); - SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); + SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); + } else { + SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); + } /* Center on display yVariation, and check window properties */ @@ -1737,11 +1816,19 @@ static int video_setWindowCenteredOnDisplay(void *arg) SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display ID (current: %d, expected: %d)", currentDisplay, expectedDisplay); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display ID (current: %d, expected: %d)", currentDisplay, expectedDisplay); + } else { + SDLTest_Log("Skipping display ID validation: Wayland driver does not support window positioning"); + } SDLTest_AssertCheck(currentW == w, "Validate width (current: %d, expected: %d)", currentW, w); SDLTest_AssertCheck(currentH == h, "Validate height (current: %d, expected: %d)", currentH, h); - SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); - SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); + if (!video_driver_is_wayland) { + SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); + SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); + } else { + SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); + } /* Clean up */ destroyVideoSuiteTestWindow(window);