Track keyboard grab state internally rather than using SDL

Versions of sdl2-compat prior to 2.32.64 (and native SDL3) won't
set the grab flag if grabbing the keyboard fails, even though the
compositor still may be exclusively passing system keys to us via
some external configuration by the user. This causes the super key
to not be sent to the host, because we think the client OS will
consume it and don't want to duplicate the input.

Fixes #1900
This commit is contained in:
Cameron Gutman
2026-06-06 16:11:37 -05:00
parent 19d77704ba
commit 534ce02756
2 changed files with 15 additions and 14 deletions
+13 -13
View File
@@ -19,7 +19,8 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i
m_PendingMouseButtonsAllUpOnVideoRegionLeave(false),
m_PointerRegionLockActive(false),
m_PointerRegionLockToggledByUser(false),
m_FakeCaptureActive(false),
m_FakeMouseCaptureActive(false),
m_KeyboardCaptureActive(false),
m_CaptureSystemKeysMode(prefs.captureSysKeysMode),
m_MouseCursorCapturedVisibilityState(SDL_DISABLE),
m_LongPressTimer(0),
@@ -319,7 +320,7 @@ bool SdlInputHandler::isCaptureActive()
}
// Some platforms don't support SDL_SetRelativeMouseMode
return m_FakeCaptureActive;
return m_FakeMouseCaptureActive;
}
void SdlInputHandler::updateKeyboardGrabState()
@@ -342,6 +343,8 @@ void SdlInputHandler::updateKeyboardGrabState()
// SDL 2.0.18 adds keyboard grab on macOS (if built with non-AppStore APIs).
SDL_SetWindowKeyboardGrab(m_Window, shouldGrab ? SDL_TRUE : SDL_FALSE);
#endif
m_KeyboardCaptureActive = shouldGrab;
}
bool SdlInputHandler::isSystemKeyCaptureActive()
@@ -354,15 +357,12 @@ bool SdlInputHandler::isSystemKeyCaptureActive()
return false;
}
// NB: We used to check SDL_WINDOW_KEYBOARD_GRABBED here, but this isn't
// always set when capture "fails" on SDL3, even though the user may have
// configured the compositor to pass through system keys to us anyway.
// See issues #1776 and #1900 for details.
Uint32 windowFlags = SDL_GetWindowFlags(m_Window);
if (!(windowFlags & SDL_WINDOW_INPUT_FOCUS)
#if SDL_VERSION_ATLEAST(2, 0, 15)
|| !(windowFlags & SDL_WINDOW_KEYBOARD_GRABBED)
#else
|| !(windowFlags & SDL_WINDOW_INPUT_GRABBED)
#endif
)
{
if (!(windowFlags & SDL_WINDOW_INPUT_FOCUS) || !m_KeyboardCaptureActive) {
return false;
}
@@ -381,7 +381,7 @@ void SdlInputHandler::setCaptureActive(bool active)
if (m_AbsoluteMouseMode || SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
// Relative mouse mode didn't work or was disabled, so we'll just hide the cursor
SDL_ShowCursor(m_MouseCursorCapturedVisibilityState);
m_FakeCaptureActive = true;
m_FakeMouseCaptureActive = true;
}
// Synchronize the client and host cursor when activating absolute capture
@@ -411,10 +411,10 @@ void SdlInputHandler::setCaptureActive(bool active)
}
}
else {
if (m_FakeCaptureActive) {
if (m_FakeMouseCaptureActive) {
// Display the cursor again
SDL_ShowCursor(SDL_ENABLE);
m_FakeCaptureActive = false;
m_FakeMouseCaptureActive = false;
}
else {
SDL_SetRelativeMouseMode(SDL_FALSE);
+2 -1
View File
@@ -218,7 +218,8 @@ private:
int m_GamepadMask;
GamepadState m_GamepadState[MAX_GAMEPADS];
QSet<short> m_KeysDown;
bool m_FakeCaptureActive;
bool m_FakeMouseCaptureActive;
bool m_KeyboardCaptureActive;
QString m_OldIgnoreDevices;
QString m_OldIgnoreDevicesExcept;
QStringList m_IgnoreDeviceGuids;