From 908d91ff3fe35c9d4daffc14dcf884be8845dbef Mon Sep 17 00:00:00 2001 From: pchome Date: Fri, 1 May 2026 14:32:18 +0300 Subject: [PATCH] SDLBackend: do not leak Super+KEY shortcuts to DE Some gamescope shortcuts are DE default shortcuts. For example `Super+I` is KDE Plasma Settings shortcut, and `Super+B` is Power Profile Switch in Plasma Power Management. Funny enough `Super+G` is the default shortcut too, but keyboard grab seems resets the key modifier (?) so it not detected by DE. Also user must press the Super key again after that for other gamescope shorts to work. Maybe a bit hackky solution is to temporary grab keyboard (if not already grabbed) while the Super key remain pressed and release grab when the key released. During the key grab we lose key modifier (as was mentioned above), so the same toggle-variable used as alternative modifier indicator. NOTE: DE will not receive Super+KEY shortcuts in this case. If there were some important ones for users (e.g. Super+PrintScreen). Issue: ValveSoftware/gamescope#2156 --- src/Backends/SDLBackend.cpp | 23 ++++++++++++++++++++--- src/main.cpp | 1 + src/main.hpp | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Backends/SDLBackend.cpp b/src/Backends/SDLBackend.cpp index 87bde7e2f1..faf221309f 100644 --- a/src/Backends/SDLBackend.cpp +++ b/src/Backends/SDLBackend.cpp @@ -742,6 +742,12 @@ namespace gamescope { break; } + + // Temporary grab keyboard while Super is pressed + if (!g_bGrabbed && !g_bShortcutGrabbed && key == KEY_LEFTMETA) { + g_bShortcutGrabbed = true; + SDL_SetWindowKeyboardGrab(m_Connector.GetSDLWindow(), g_bShortcutGrabbed); + } } } [[fallthrough]]; @@ -749,7 +755,7 @@ namespace gamescope { uint32_t key = SDLScancodeToLinuxKey( event.key.keysym.scancode ); - if ( event.type == SDL_KEYUP && ( event.key.keysym.mod & KMOD_LGUI ) ) + if ( event.type == SDL_KEYUP && ( (event.key.keysym.mod & KMOD_LGUI) != 0 || g_bShortcutGrabbed ) ) { bool handled = true; switch ( key ) @@ -781,14 +787,25 @@ namespace gamescope case KEY_S: gamescope::CScreenshotManager::Get().TakeScreenshot( true ); break; - case KEY_G: + case KEY_G: { + // Reset shortcut grab and allow normal grab w/ title change + if (g_bShortcutGrabbed) { + g_bShortcutGrabbed = false; + } g_bGrabbed = !g_bGrabbed; SDL_SetWindowKeyboardGrab( m_Connector.GetSDLWindow(), g_bGrabbed ? SDL_TRUE : SDL_FALSE ); SDL_Event event; event.type = GetUserEventIndex( GAMESCOPE_SDL_EVENT_TITLE ); SDL_PushEvent( &event ); - break; + } break; + case KEY_LEFTMETA: { + // Release shortcut grab + if (g_bShortcutGrabbed) { + g_bShortcutGrabbed = false; + SDL_SetWindowKeyboardGrab(m_Connector.GetSDLWindow(), g_bShortcutGrabbed); + } + } break; default: handled = false; } diff --git a/src/main.cpp b/src/main.cpp index 1397028e7f..87607c080b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -303,6 +303,7 @@ bool g_bFullscreen = false; bool g_bForceRelativeMouse = false; bool g_bGrabbed = false; +bool g_bShortcutGrabbed = false; float g_mouseSensitivity = 1.0; diff --git a/src/main.hpp b/src/main.hpp index 2e6fb833af..3548d7737a 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -25,6 +25,7 @@ extern bool g_bForceInternal; extern bool g_bFullscreen; extern bool g_bGrabbed; +extern bool g_bShortcutGrabbed; extern float g_mouseSensitivity; extern const char *g_sOutputName;