SDL 3 Cursor freeze when switching Windowed <-> Fullscreen with hidden cursor on Wayland
In Exult, the cursor gets a SDL_HideCursor to display the original game pointer instead.
In SDL 3, switching back and forth from Windowed Exult to Fullscreen Exult results in a cursor freeze under Linux over Wayland.
This can be reproduced with the SDL 3 testwm - Linux over Wayland - provided one adds in test/testwm.c, main function the two lines at the bottom of :
...
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) {
SDLTest_CommonQuit(state);
return 1;
}
SDL_HideCursor(); // Hide the cursor
SDL_ShowCursor(); // Show the cursor
...
With that change, testwm works normally until one switches it to Fullscreen ( Alt-Enter ). Then the cursor is frozen, unless it was outside of the testwm window when the switch occurred.
And then at the switch back to Windowed, the cursor is unconditionally frozen.
For what it is worth :
- When the freeze occurs, SDL does not receive any mouse motion event from Wayland. Unless it has received first a mouse enter event, that is, in the case where the cursor was outside the
testwmwindow prior to the switch to fullscreen. - In
src/video/wayland/SDL_waylandmouse.c,Wayland_ShowCursor( NULL )[ coming fromSDL_HideCursor] performs awl_pointer_set_cursor(pointer, input->pointer_enter_serial, NULL, 0, 0);. Wayland_ShowCursor( aCursor )[ fromSDL_ShowCursor] does not perform the oppositewl_pointer_set_cursor(pointer, input->pointer_enter_serial, data->surface, data->hot_x / scale, data->hot_y / scale);because it has used theWayland_SetSystemCursorShapepath instead.
Can you provide more details about your system, particularly what desktop you are running? Quickly trying your repro case on my desktop with Fedora 40 + GNOME doesn't reproduce your issue.
Fedora 40 Plasma over Wayland.
With SDL 3 at main commit 60d355eb0 [origin/main] Sync SDL3 wiki -> header.
Add two lines to test/testwm.c :
diff --git a/test/testwm.c b/test/testwm.c
index 3e1a75978..c191a8067 100644
--- a/test/testwm.c
+++ b/test/testwm.c
@@ -289,6 +289,8 @@ int main(int argc, char *argv[])
SDL_RenderClear(renderer);
}
+ SDL_HideCursor();
+ SDL_ShowCursor();
/* Main render loop */
done = 0;
#ifdef SDL_PLATFORM_EMSCRIPTEN
Build SDL 3, run testwm, bring the cursor into the testwm window, switch to fullscreen with Alt-Enter, cursor is frozen.
Perfect, thank you!
Ah, the cursor visibility flag wasn't being set properly when setting the cursor via the cursor shape protocol, which in turn caused the pointer warp emulation to activate when the video core attempted to warp the pointer when toggling fullscreen, which resulted in the pointer being locked and staying locked.
Backported to SDL2 as well.