From 56f184393fced4b362e1bdb57900af47aa2f6324 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 19 May 2022 19:14:55 -0500 Subject: [PATCH] Allow the cursor lock toggle to work in full-screen mode Fixes #793 --- app/streaming/input/input.cpp | 23 ++++------------------- app/streaming/input/input.h | 1 + app/streaming/input/keyboard.cpp | 6 ++++++ app/streaming/input/mouse.cpp | 14 ++++++++++---- app/streaming/session.cpp | 11 +++-------- 5 files changed, 24 insertions(+), 31 deletions(-) diff --git a/app/streaming/input/input.cpp b/app/streaming/input/input.cpp index 0588f10e..1ed2cfae 100644 --- a/app/streaming/input/input.cpp +++ b/app/streaming/input/input.cpp @@ -22,6 +22,7 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s m_MouseWasInVideoRegion(false), m_PendingMouseButtonsAllUpOnVideoRegionLeave(false), m_PointerRegionLockActive(false), + m_PointerRegionLockToggledByUser(false), m_FakeCaptureActive(false), m_CaptureSystemKeysMode(prefs.captureSysKeysMode), m_MouseCursorCapturedVisibilityState(SDL_DISABLE), @@ -339,27 +340,11 @@ void SdlInputHandler::updateKeyboardGrabState() // Don't close the window on Alt+F4 when keyboard grab is enabled SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, shouldGrab ? "1" : "0"); - if (shouldGrab) { #if SDL_VERSION_ATLEAST(2, 0, 15) - // On SDL 2.0.15, we can get keyboard-only grab on Win32, X11, and Wayland. - // This does nothing on macOS but it sets the SDL_WINDOW_KEYBOARD_GRABBED flag - // that we look for to see if keyboard capture is enabled. We'll handle macOS - // ourselves below using the private CGSSetGlobalHotKeyOperatingMode() API. - SDL_SetWindowKeyboardGrab(m_Window, SDL_TRUE); -#else - // If we're in full-screen desktop mode and SDL doesn't have keyboard grab yet, - // grab the cursor (will grab the keyboard too on X11). - if (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN) { - SDL_SetWindowGrab(m_Window, SDL_TRUE); - } + // On SDL 2.0.15+, we can get keyboard-only grab on Win32, X11, and Wayland. + // 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 - } - else { -#if SDL_VERSION_ATLEAST(2, 0, 15) - // Allow the keyboard to leave the window - SDL_SetWindowKeyboardGrab(m_Window, SDL_FALSE); -#endif - } } bool SdlInputHandler::isSystemKeyCaptureActive() diff --git a/app/streaming/input/input.h b/app/streaming/input/input.h index 12b7512c..269989eb 100644 --- a/app/streaming/input/input.h +++ b/app/streaming/input/input.h @@ -160,6 +160,7 @@ private: bool m_MouseWasInVideoRegion; bool m_PendingMouseButtonsAllUpOnVideoRegionLeave; bool m_PointerRegionLockActive; + bool m_PointerRegionLockToggledByUser; int m_GamepadMask; GamepadState m_GamepadState[MAX_GAMEPADS]; diff --git a/app/streaming/input/keyboard.cpp b/app/streaming/input/keyboard.cpp index 7f82e094..ac606556 100644 --- a/app/streaming/input/keyboard.cpp +++ b/app/streaming/input/keyboard.cpp @@ -130,6 +130,12 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected pointer region lock toggle combo"); m_PointerRegionLockActive = !m_PointerRegionLockActive; + + // Remember that the user changed this manually, so we don't mess with it anymore + // during windowed <-> full-screen transitions. + m_PointerRegionLockToggledByUser = true; + + // Apply the new region lock updatePointerRegionLock(); break; diff --git a/app/streaming/input/mouse.cpp b/app/streaming/input/mouse.cpp index 61ff9ba9..cf53b926 100644 --- a/app/streaming/input/mouse.cpp +++ b/app/streaming/input/mouse.cpp @@ -291,10 +291,16 @@ void SdlInputHandler::updatePointerRegionLock() return; } - // If we're in full-screen exclusive mode or region lock is enabled, grab the cursor so it can't accidentally leave our window. - if (isCaptureActive() && - (m_PointerRegionLockActive || - (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN)) { + // Our pointer lock behavior tracks with the fullscreen mode unless the user has + // toggled it themselves using the keyboard shortcut. If that's the case, they + // have full control over it and we don't touch it anymore. + if (!m_PointerRegionLockToggledByUser) { + // Lock the pointer in true full-screen mode and leave it unlocked in other modes + m_PointerRegionLockActive = (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN; + } + + // If region lock is enabled, grab the cursor so it can't accidentally leave our window. + if (isCaptureActive() && m_PointerRegionLockActive) { #if SDL_VERSION_ATLEAST(2, 0, 18) SDL_Rect src, dst; diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index ee331e59..cc057877 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -1068,18 +1068,10 @@ void Session::toggleFullscreen() bool fullScreen = !(SDL_GetWindowFlags(m_Window) & m_FullScreenFlag); if (fullScreen) { - if (m_FullScreenFlag == SDL_WINDOW_FULLSCREEN && m_InputHandler->isCaptureActive()) { - // Confine the cursor to the window if we're capturing input while transitioning to full screen. - SDL_SetWindowGrab(m_Window, SDL_TRUE); - } - SDL_SetWindowResizable(m_Window, SDL_FALSE); SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag); } else { - // Unconfine the cursor - SDL_SetWindowGrab(m_Window, SDL_FALSE); - SDL_SetWindowFullscreen(m_Window, 0); SDL_SetWindowResizable(m_Window, SDL_TRUE); @@ -1089,6 +1081,9 @@ void Session::toggleFullscreen() // Input handler might need to start/stop keyboard grab after changing modes m_InputHandler->updateKeyboardGrabState(); + + // Input handler might need stop/stop mouse grab after changing modes + m_InputHandler->updatePointerRegionLock(); } void Session::notifyMouseEmulationMode(bool enabled)