Add pointer lock key combo

Fixes #737
This commit is contained in:
Cameron Gutman 2022-03-29 18:26:09 -05:00
parent 742f1b1283
commit 6972573a6e
5 changed files with 68 additions and 17 deletions

View file

@ -21,6 +21,7 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
m_MousePositionLock(0), m_MousePositionLock(0),
m_MouseWasInVideoRegion(false), m_MouseWasInVideoRegion(false),
m_PendingMouseButtonsAllUpOnVideoRegionLeave(false), m_PendingMouseButtonsAllUpOnVideoRegionLeave(false),
m_PointerRegionLockActive(false),
m_FakeCaptureActive(false), m_FakeCaptureActive(false),
m_CaptureSystemKeysMode(prefs.captureSysKeysMode), m_CaptureSystemKeysMode(prefs.captureSysKeysMode),
m_MouseCursorCapturedVisibilityState(SDL_DISABLE), m_MouseCursorCapturedVisibilityState(SDL_DISABLE),
@ -115,6 +116,11 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
m_SpecialKeyCombos[KeyComboPasteText].scanCode = SDL_SCANCODE_V; m_SpecialKeyCombos[KeyComboPasteText].scanCode = SDL_SCANCODE_V;
m_SpecialKeyCombos[KeyComboPasteText].enabled = true; m_SpecialKeyCombos[KeyComboPasteText].enabled = true;
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCombo = KeyComboTogglePointerRegionLock;
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCode = SDLK_l;
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].scanCode = SDL_SCANCODE_L;
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].enabled = true;
m_OldIgnoreDevices = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES); m_OldIgnoreDevices = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES);
m_OldIgnoreDevicesExcept = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT); m_OldIgnoreDevicesExcept = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT);
@ -389,15 +395,6 @@ bool SdlInputHandler::isSystemKeyCaptureActive()
void SdlInputHandler::setCaptureActive(bool active) void SdlInputHandler::setCaptureActive(bool active)
{ {
if (active) { if (active) {
// If we're in full-screen exclusive mode, grab the cursor so it can't accidentally leave our window.
if ((SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
#if SDL_VERSION_ATLEAST(2, 0, 15)
SDL_SetWindowMouseGrab(m_Window, SDL_TRUE);
#else
SDL_SetWindowGrab(m_Window, SDL_TRUE);
#endif
}
// If we're in relative mode, try to activate SDL's relative mouse mode // If we're in relative mode, try to activate SDL's relative mouse mode
if (m_AbsoluteMouseMode || SDL_SetRelativeMouseMode(SDL_TRUE) < 0) { if (m_AbsoluteMouseMode || SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
// Relative mouse mode didn't work or was disabled, so we'll just hide the cursor // Relative mouse mode didn't work or was disabled, so we'll just hide the cursor
@ -433,16 +430,11 @@ void SdlInputHandler::setCaptureActive(bool active)
else { else {
SDL_SetRelativeMouseMode(SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE);
} }
#if SDL_VERSION_ATLEAST(2, 0, 15)
// Allow the cursor to leave the bounds of our window again.
SDL_SetWindowMouseGrab(m_Window, SDL_FALSE);
#else
// Allow the cursor to leave the bounds of our window again.
SDL_SetWindowGrab(m_Window, SDL_FALSE);
#endif
} }
// Update mouse pointer region constraints
updatePointerRegionLock();
// Now update the keyboard grab // Now update the keyboard grab
updateKeyboardGrabState(); updateKeyboardGrabState();
} }

View file

@ -93,6 +93,8 @@ public:
void updateKeyboardGrabState(); void updateKeyboardGrabState();
void updatePointerRegionLock();
static static
QString getUnmappedGamepads(); QString getUnmappedGamepads();
@ -106,6 +108,7 @@ private:
KeyComboToggleCursorHide, KeyComboToggleCursorHide,
KeyComboToggleMinimize, KeyComboToggleMinimize,
KeyComboPasteText, KeyComboPasteText,
KeyComboTogglePointerRegionLock,
KeyComboMax KeyComboMax
}; };
@ -156,6 +159,7 @@ private:
SDL_atomic_t m_MousePositionUpdated; SDL_atomic_t m_MousePositionUpdated;
bool m_MouseWasInVideoRegion; bool m_MouseWasInVideoRegion;
bool m_PendingMouseButtonsAllUpOnVideoRegionLeave; bool m_PendingMouseButtonsAllUpOnVideoRegionLeave;
bool m_PointerRegionLockActive;
int m_GamepadMask; int m_GamepadMask;
GamepadState m_GamepadState[MAX_GAMEPADS]; GamepadState m_GamepadState[MAX_GAMEPADS];

View file

@ -126,6 +126,13 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo)
break; break;
} }
case KeyComboTogglePointerRegionLock:
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Detected pointer region lock toggle combo");
m_PointerRegionLockActive = !m_PointerRegionLockActive;
updatePointerRegionLock();
break;
default: default:
Q_UNREACHABLE(); Q_UNREACHABLE();
} }

View file

@ -272,3 +272,48 @@ Uint32 SdlInputHandler::mouseMoveTimerCallback(Uint32 interval, void *param)
return interval; return interval;
} }
void SdlInputHandler::updatePointerRegionLock()
{
// Pointer region lock is irrelevant in relative mouse mode
if (SDL_GetRelativeMouseMode()) {
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)) {
#if SDL_VERSION_ATLEAST(2, 0, 18)
SDL_Rect src, dst;
src.x = src.y = 0;
src.w = m_StreamWidth;
src.h = m_StreamHeight;
dst.x = dst.y = 0;
SDL_GetWindowSize(m_Window, &dst.w, &dst.h);
// Use the stream and window sizes to determine the video region
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
// SDL 2.0.18 lets us lock the cursor to a specific region
SDL_SetWindowMouseRect(m_Window, &dst);
#elif SDL_VERSION_ATLEAST(2, 0, 15)
// SDL 2.0.15 only lets us lock the cursor to the whole window
SDL_SetWindowMouseGrab(m_Window, SDL_TRUE);
#else
SDL_SetWindowGrab(m_Window, SDL_TRUE);
#endif
}
else {
// Allow the cursor to leave the bounds of our video region or window
#if SDL_VERSION_ATLEAST(2, 0, 18)
SDL_SetWindowMouseRect(m_Window, nullptr);
#elif SDL_VERSION_ATLEAST(2, 0, 15)
SDL_SetWindowMouseGrab(m_Window, SDL_FALSE);
#else
SDL_SetWindowGrab(m_Window, SDL_FALSE);
#endif
}
}

View file

@ -1708,6 +1708,9 @@ void Session::execInternal()
// of recreating our decoder at the time the HDR transition happens. // of recreating our decoder at the time the HDR transition happens.
m_VideoDecoder->setHdrMode(LiGetCurrentHostDisplayHdrMode()); m_VideoDecoder->setHdrMode(LiGetCurrentHostDisplayHdrMode());
// After a window resize, we need to reset the pointer lock region
m_InputHandler->updatePointerRegionLock();
SDL_AtomicUnlock(&m_DecoderLock); SDL_AtomicUnlock(&m_DecoderLock);
break; break;