Add a mouse capture fallback if SDL_SetRelativeMouseMode() fails

This commit is contained in:
Cameron Gutman
2019-07-02 22:17:18 -07:00
parent 22162dda83
commit 16b301236b
3 changed files with 46 additions and 12 deletions
+38 -8
View File
@@ -53,6 +53,7 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
: m_MultiController(prefs.multiController), : m_MultiController(prefs.multiController),
m_GamepadMouse(prefs.gamepadMouse), m_GamepadMouse(prefs.gamepadMouse),
m_MouseMoveTimer(0), m_MouseMoveTimer(0),
m_FakeCaptureActive(false),
m_LeftButtonReleaseTimer(0), m_LeftButtonReleaseTimer(0),
m_RightButtonReleaseTimer(0), m_RightButtonReleaseTimer(0),
m_DragTimer(0), m_DragTimer(0),
@@ -213,7 +214,7 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
"Detected mouse capture toggle combo (SDLK)"); "Detected mouse capture toggle combo (SDLK)");
// Stop handling future input // Stop handling future input
SDL_SetRelativeMouseMode((SDL_bool)!SDL_GetRelativeMouseMode()); setCaptureActive(!isCaptureActive());
// Force raise all keys to ensure they aren't stuck, // Force raise all keys to ensure they aren't stuck,
// since we won't get their key up events. // since we won't get their key up events.
@@ -261,7 +262,7 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
"Detected mouse capture toggle combo (scancode)"); "Detected mouse capture toggle combo (scancode)");
// Stop handling future input // Stop handling future input
SDL_SetRelativeMouseMode((SDL_bool)!SDL_GetRelativeMouseMode()); setCaptureActive(!isCaptureActive());
// Force raise all keys to ensure they aren't stuck, // Force raise all keys to ensure they aren't stuck,
// since we won't get their key up events. // since we won't get their key up events.
@@ -294,7 +295,7 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
} }
} }
if (!SDL_GetRelativeMouseMode()) { if (!isCaptureActive()) {
// Not capturing // Not capturing
return; return;
} }
@@ -540,11 +541,11 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event)
// the pressed event was consumed by this code). // the pressed event was consumed by this code).
if (event->button == SDL_BUTTON_LEFT && if (event->button == SDL_BUTTON_LEFT &&
event->state == SDL_RELEASED && event->state == SDL_RELEASED &&
!SDL_GetRelativeMouseMode()) { !isCaptureActive()) {
SDL_SetRelativeMouseMode(SDL_TRUE); setCaptureActive(true);
return; return;
} }
else if (!SDL_GetRelativeMouseMode()) { else if (!isCaptureActive()) {
// Not capturing // Not capturing
return; return;
} }
@@ -585,7 +586,7 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event)
void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
{ {
if (!SDL_GetRelativeMouseMode()) { if (!isCaptureActive()) {
// Not capturing // Not capturing
return; return;
} }
@@ -602,7 +603,7 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event)
{ {
if (!SDL_GetRelativeMouseMode()) { if (!isCaptureActive()) {
// Not capturing // Not capturing
return; return;
} }
@@ -1299,6 +1300,35 @@ void SdlInputHandler::raiseAllKeys()
m_KeysDown.clear(); m_KeysDown.clear();
} }
bool SdlInputHandler::isCaptureActive()
{
if (SDL_GetRelativeMouseMode()) {
return true;
}
// Some platforms don't support SDL_SetRelativeMouseMode
return m_FakeCaptureActive;
}
void SdlInputHandler::setCaptureActive(bool active)
{
if (active) {
// Try to activate SDL's relative mouse mode
if (SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
// Relative mouse mode didn't work, so we'll use fake capture
SDL_ShowCursor(SDL_DISABLE);
m_FakeCaptureActive = true;
}
}
else if (m_FakeCaptureActive) {
SDL_ShowCursor(SDL_ENABLE);
m_FakeCaptureActive = false;
}
else {
SDL_SetRelativeMouseMode(SDL_FALSE);
}
}
QString SdlInputHandler::getUnmappedGamepads() QString SdlInputHandler::getUnmappedGamepads()
{ {
QString ret; QString ret;
+5
View File
@@ -64,6 +64,10 @@ public:
void raiseAllKeys(); void raiseAllKeys();
bool isCaptureActive();
void setCaptureActive(bool active);
static static
QString getUnmappedGamepads(); QString getUnmappedGamepads();
@@ -96,6 +100,7 @@ private:
int m_GamepadMask; int m_GamepadMask;
GamepadState m_GamepadState[MAX_GAMEPADS]; GamepadState m_GamepadState[MAX_GAMEPADS];
QSet<short> m_KeysDown; QSet<short> m_KeysDown;
bool m_FakeCaptureActive;
SDL_TouchFingerEvent m_TouchDownEvent[MAX_FINGERS]; SDL_TouchFingerEvent m_TouchDownEvent[MAX_FINGERS];
float m_CumulativeDelta[MAX_FINGERS]; float m_CumulativeDelta[MAX_FINGERS];
+3 -4
View File
@@ -1101,20 +1101,19 @@ void Session::exec(int displayOriginX, int displayOriginY)
SDL_GetWindowPosition(m_Window, &x, &y); SDL_GetWindowPosition(m_Window, &x, &y);
SDL_GetWindowSize(m_Window, &width, &height); SDL_GetWindowSize(m_Window, &width, &height);
if (mouseX > x && mouseX < x+width && mouseY > y && mouseY < y+height) { if (mouseX > x && mouseX < x+width && mouseY > y && mouseY < y+height) {
SDL_SetRelativeMouseMode(SDL_TRUE); m_InputHandler->setCaptureActive(true);
} }
} }
} }
#endif #endif
if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
// Release mouse cursor when another window is activated (e.g. by using ALT+TAB). // Release mouse cursor when another window is activated (e.g. by using ALT+TAB).
// This lets user to interact with our window's title bar and with the buttons in it. // This lets user to interact with our window's title bar and with the buttons in it.
// Doing this while the window is full-screen breaks the transition out of FS // Doing this while the window is full-screen breaks the transition out of FS
// (desktop and exclusive), so we must check for that before releasing mouse capture. // (desktop and exclusive), so we must check for that before releasing mouse capture.
if (!(SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN)) { if (!(SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN)) {
SDL_SetRelativeMouseMode(SDL_FALSE); m_InputHandler->setCaptureActive(false);
} }
// Raise all keys that are currently pressed. If we don't do this, certain keys // Raise all keys that are currently pressed. If we don't do this, certain keys
@@ -1247,7 +1246,7 @@ void Session::exec(int displayOriginX, int displayOriginY)
DispatchDeferredCleanup: DispatchDeferredCleanup:
// Uncapture the mouse and hide the window immediately, // Uncapture the mouse and hide the window immediately,
// so we can return to the Qt GUI ASAP. // so we can return to the Qt GUI ASAP.
SDL_SetRelativeMouseMode(SDL_FALSE); m_InputHandler->setCaptureActive(false);
SDL_EnableScreenSaver(); SDL_EnableScreenSaver();
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "0"); SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "0");