From ef6dfa6d91e39e6c158908fa7e35de452404aa7a Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 11 Apr 2020 16:12:18 -0700 Subject: [PATCH] Add basic support for absolute mouse input --- app/streaming/input.cpp | 76 +++++++++++++++++++++++---- app/streaming/input.h | 5 +- app/streaming/session.cpp | 4 +- moonlight-common-c/moonlight-common-c | 2 +- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/app/streaming/input.cpp b/app/streaming/input.cpp index bcf711da..dad503a3 100644 --- a/app/streaming/input.cpp +++ b/app/streaming/input.cpp @@ -3,6 +3,7 @@ #include "streaming/session.h" #include "settings/mappingmanager.h" #include "path.h" +#include "streamutils.h" #include #include @@ -65,7 +66,8 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s m_DragButton(0), m_NumFingersDown(0), m_StreamWidth(streamWidth), - m_StreamHeight(streamHeight) + m_StreamHeight(streamHeight), + m_AbsoluteMouseMode(false) { // Allow gamepad input when the app doesn't have focus SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); @@ -250,6 +252,21 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event) raiseAllKeys(); return; } + // Check for the mouse mode combo (Ctrl+Alt+Shift+M) unless on EGLFS which has no window manager + else if (event->keysym.sym == SDLK_m && QGuiApplication::platformName() != "eglfs") { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected mouse mode toggle combo (SDLK)"); + + // Uncapture input + setCaptureActive(false); + + // Toggle mouse mode + m_AbsoluteMouseMode = !m_AbsoluteMouseMode; + + // Recapture input + setCaptureActive(true); + return; + } else if (event->keysym.sym == SDLK_x && QGuiApplication::platformName() != "eglfs") { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected full-screen toggle combo (SDLK)"); @@ -310,6 +327,21 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event) raiseAllKeys(); return; } + // Check for the mouse mode toggle combo (Ctrl+Alt+Shift+M) unless on EGLFS which has no window manager + else if (event->keysym.scancode == SDL_SCANCODE_M && QGuiApplication::platformName() != "eglfs") { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected mouse mode toggle combo (scancode)"); + + // Uncapture input + setCaptureActive(false); + + // Toggle mouse mode + m_AbsoluteMouseMode = !m_AbsoluteMouseMode; + + // Recapture input + setCaptureActive(true); + return; + } else if (event->keysym.scancode == SDL_SCANCODE_S) { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected stats toggle combo (scancode)"); @@ -633,7 +665,7 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event) button); } -void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) +void SdlInputHandler::handleMouseMotionEvent(SDL_Window* window, SDL_MouseMotionEvent* event) { if (!isCaptureActive()) { // Not capturing @@ -644,10 +676,36 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) return; } - // Batch until the next mouse polling window or we'll get awful - // input lag everything except GFE 3.14 and 3.15. - SDL_AtomicAdd(&m_MouseDeltaX, event->xrel); - SDL_AtomicAdd(&m_MouseDeltaY, event->yrel); + if (m_AbsoluteMouseMode) { + SDL_Rect src, dst; + + src.x = src.y = 0; + src.w = m_StreamWidth; + src.h = m_StreamHeight; + + dst.x = dst.y = 0; + SDL_GetWindowSize(window, &dst.w, &dst.h); + + // Use the stream and window sizes to determine the video region + StreamUtils::scaleSourceToDestinationSurface(&src, &dst); + + // Ignore motion outside the video region + if (event->x < dst.x || event->y < dst.y || + event->x > dst.x + dst.w || event->y > dst.y + dst.h) { + return; + } + + // Send the mouse position update with coordinates relative to + // the video region. + LiSendMousePositionEvent(event->x - dst.x, event->y - dst.y, + dst.w, dst.h); + } + else { + // Batch until the next mouse polling window or we'll get awful + // input lag everything except GFE 3.14 and 3.15. + SDL_AtomicAdd(&m_MouseDeltaX, event->xrel); + SDL_AtomicAdd(&m_MouseDeltaY, event->yrel); + } } void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) @@ -1196,7 +1254,7 @@ void SdlInputHandler::rumble(unsigned short controllerNumber, unsigned short low #endif } -void SdlInputHandler::handleTouchFingerEvent(SDL_TouchFingerEvent* event) +void SdlInputHandler::handleTouchFingerEvent(SDL_Window*, SDL_TouchFingerEvent* event) { int fingerIndex = -1; @@ -1396,8 +1454,8 @@ bool SdlInputHandler::isCaptureActive() void SdlInputHandler::setCaptureActive(bool active) { if (active) { - // Try to activate SDL's relative mouse mode - if (SDL_SetRelativeMouseMode(SDL_TRUE) < 0) { + // If we're in relative mode, try to activate SDL's relative mouse mode + if (m_AbsoluteMouseMode || SDL_SetRelativeMouseMode(SDL_TRUE) < 0) { // Relative mouse mode didn't work, so we'll use fake capture SDL_ShowCursor(SDL_DISABLE); m_FakeCaptureActive = true; diff --git a/app/streaming/input.h b/app/streaming/input.h index 073c3cc1..eb1b65a3 100644 --- a/app/streaming/input.h +++ b/app/streaming/input.h @@ -47,7 +47,7 @@ public: void handleMouseButtonEvent(SDL_MouseButtonEvent* event); - void handleMouseMotionEvent(SDL_MouseMotionEvent* event); + void handleMouseMotionEvent(SDL_Window* window, SDL_MouseMotionEvent* event); void handleMouseWheelEvent(SDL_MouseWheelEvent* event); @@ -61,7 +61,7 @@ public: void rumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor); - void handleTouchFingerEvent(SDL_TouchFingerEvent* event); + void handleTouchFingerEvent(SDL_Window* window, SDL_TouchFingerEvent* event); int getAttachedGamepadMask(); @@ -114,6 +114,7 @@ private: int m_NumFingersDown; int m_StreamWidth; int m_StreamHeight; + bool m_AbsoluteMouseMode; static const int k_ButtonMap[]; }; diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index d1e42339..7b603244 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -1318,7 +1318,7 @@ void Session::exec(int displayOriginX, int displayOriginY) m_InputHandler->handleMouseButtonEvent(&event.button); break; case SDL_MOUSEMOTION: - m_InputHandler->handleMouseMotionEvent(&event.motion); + m_InputHandler->handleMouseMotionEvent(m_Window, &event.motion); break; case SDL_MOUSEWHEEL: m_InputHandler->handleMouseWheelEvent(&event.wheel); @@ -1340,7 +1340,7 @@ void Session::exec(int displayOriginX, int displayOriginY) case SDL_FINGERDOWN: case SDL_FINGERMOTION: case SDL_FINGERUP: - m_InputHandler->handleTouchFingerEvent(&event.tfinger); + m_InputHandler->handleTouchFingerEvent(m_Window, &event.tfinger); break; } } diff --git a/moonlight-common-c/moonlight-common-c b/moonlight-common-c/moonlight-common-c index f0c3b57d..247b1fe0 160000 --- a/moonlight-common-c/moonlight-common-c +++ b/moonlight-common-c/moonlight-common-c @@ -1 +1 @@ -Subproject commit f0c3b57d11003ab2a7c1803d6faca8701ae01b3f +Subproject commit 247b1fe0e32d80ce02ede4c2b4a835b9c085abe4