From 463bd7acf9e5d4a3c86d66119b797b07730f4e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 3 Sep 2026 08:13:54 -0600 Subject: [PATCH] SDL: Prefer Wayland when we're in a Wayland session SDL doesn't reliably pick Wayland on its own - on a machine with a working Wayland compositor but no XDG_SESSION_TYPE it still chose x11, putting us on XWayland. Ask for Wayland when WAYLAND_DISPLAY is set, respect SDL_VIDEO_DRIVER if the user set it, and fall back to letting SDL choose if Wayland then fails to initialize. Also log the video driver we ended up with, which should help triage the Wayland/X11 reports. Fixes #21080 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq --- SDL/SDLMain.cpp | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 57aa4a608a..b3a89ff63d 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -1793,6 +1793,17 @@ int main(int argc, char *argv[]) { SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); #endif + // SDL's automatic pick between Wayland and X11 doesn't always land on Wayland even in a + // Wayland session, and going through XWayland instead costs us scaling and input quality. + // So ask for it explicitly when the session looks like Wayland - unless the user has set + // SDL_VIDEO_DRIVER, in which case they've already told us what they want. + // WAYLAND_DISPLAY is only set on Wayland sessions, so this is a no-op elsewhere. + bool preferWayland = false; + if (getenv("WAYLAND_DISPLAY") && !getenv("SDL_VIDEO_DRIVER")) { + SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "wayland"); + preferWayland = true; + } + bool vulkanMayBeAvailable = false; if (VulkanMayBeAvailable()) { fprintf(stderr, "DEBUG: Vulkan might be available.\n"); @@ -1821,11 +1832,30 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Failed to initialize SDL with joystick support. Retrying without.\n"); joystick_enabled = false; if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { - fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); - return 1; + bool initialized = false; + if (preferWayland) { + // Asking for Wayland may be exactly what failed, so let SDL pick instead. + fprintf(stderr, "Unable to initialize SDL with the Wayland video driver (%s). Letting SDL choose.\n", SDL_GetError()); + SDL_SetHint(SDL_HINT_VIDEO_DRIVER, nullptr); + preferWayland = false; + // Retry with joystick support - it was the video driver that failed, not the joysticks. + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_AUDIO)) { + joystick_enabled = true; + initialized = true; + } else { + initialized = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + } + } + if (!initialized) { + fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } } } + const char *videoDriver = SDL_GetCurrentVideoDriver(); + fprintf(stderr, "Info: SDL video driver: %s\n", videoDriver ? videoDriver : "(none)"); + fprintf(stderr, "Info: We compiled against SDL version %d.%d.%d", SDL_VERSIONNUM_MAJOR(compiled), SDL_VERSIONNUM_MINOR(compiled), SDL_VERSIONNUM_MICRO(compiled)); if (compiled != linked) { fprintf(stderr, ", but we are linking against SDL version %d.%d.%d., be aware that this can lead to unexpected behaviors\n", SDL_VERSIONNUM_MAJOR(linked), SDL_VERSIONNUM_MINOR(linked), SDL_VERSIONNUM_MICRO(linked));