From f426032b1b44d004efaf950879afee88246bd9d3 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Feb 2026 17:18:53 -0700 Subject: [PATCH 1/2] Ignore local qmake and build outputs --- .gitignore | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.gitignore b/.gitignore index 3a5180ac..c41d075f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,30 @@ **/.vs/ .vscode/ build/ +.qmake.cache +.qmake.stash +/Makefile +/config.log +/config.tests/ +/app/Makefile +/app/Makefile.Debug +/app/Makefile.Release +/app/release/ +/app/moonlight +/h264bitstream/Makefile +/h264bitstream/Makefile.Debug +/h264bitstream/Makefile.Release +/h264bitstream/release/ +/h264bitstream/libh264bitstream.a +/moonlight-common-c/Makefile +/moonlight-common-c/Makefile.Debug +/moonlight-common-c/Makefile.Release +/moonlight-common-c/release/ +/moonlight-common-c/libmoonlight-common-c.a +/qmdnsengine/Makefile +/qmdnsengine/Makefile.Debug +/qmdnsengine/Makefile.Release +/qmdnsengine/release/ +/qmdnsengine/libqmdnsengine.a config.tests/*/.qmake.stash config.tests/*/Makefile From f78a63ab753693258bc8f6f7e3adf7f05ae9fb93 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Feb 2026 17:18:53 -0700 Subject: [PATCH 2/2] Add runtime input toggles and gated input sending --- app/streaming/input/abstouch.cpp | 31 ++++-- app/streaming/input/gamepad.cpp | 165 ++++++++++++++++++++++++------- app/streaming/input/input.cpp | 10 ++ app/streaming/input/input.h | 2 + app/streaming/input/keyboard.cpp | 38 +++++-- app/streaming/input/mouse.cpp | 41 ++++++-- app/streaming/input/reltouch.cpp | 33 +++++-- app/streaming/session.cpp | 41 ++++++++ app/streaming/session.h | 19 ++++ 9 files changed, 312 insertions(+), 68 deletions(-) diff --git a/app/streaming/input/abstouch.cpp b/app/streaming/input/abstouch.cpp index 0fe6dac6..9e8b51a9 100644 --- a/app/streaming/input/abstouch.cpp +++ b/app/streaming/input/abstouch.cpp @@ -1,4 +1,5 @@ #include "input.h" +#include "streaming/session.h" #include #include "SDL_compat.h" @@ -7,6 +8,12 @@ #include +static bool isKeyboardMouseInputAllowed() +{ + auto session = Session::get(); + return session == nullptr || session->isKeyboardMouseInputAllowed(); +} + // How long the fingers must be stationary to start a right click #define LONG_PRESS_ACTIVATION_DELAY 650 @@ -22,8 +29,10 @@ Uint32 SdlInputHandler::longPressTimerCallback(Uint32, void*) { // Raise the left click and start a right click - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + } return 0; } @@ -110,7 +119,7 @@ void SdlInputHandler::handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event) } // Try to send it as a native pen/touch event, otherwise fall back to our touch emulation - if (LiGetHostFeatureFlags() & LI_FF_PEN_TOUCH_EVENTS) { + if (isKeyboardMouseInputAllowed() && (LiGetHostFeatureFlags() & LI_FF_PEN_TOUCH_EVENTS)) { #if SDL_VERSION_ATLEAST(2, 0, 22) bool isPen = false; @@ -197,7 +206,9 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event) short y = qMin(qMax((int)(event->y * windowHeight), dst.y), dst.y + dst.h); // Update the cursor position relative to the video region - LiSendMousePositionEvent(x - dst.x, y - dst.y, dst.w, dst.h); + if (isKeyboardMouseInputAllowed()) { + LiSendMousePositionEvent(x - dst.x, y - dst.y, dst.w, dst.h); + } } if (event->type == SDL_FINGERDOWN) { @@ -210,7 +221,9 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event) nullptr); // Left button down on finger down - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); + } } else if (event->type == SDL_FINGERUP) { m_LastTouchUpEvent = *event; @@ -220,9 +233,13 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event) m_LongPressTimer = 0; // Left button up on finger up - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + } // Raise right button too in case we triggered a long press gesture - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + } } } diff --git a/app/streaming/input/gamepad.cpp b/app/streaming/input/gamepad.cpp index e0d7f004..d5171f22 100644 --- a/app/streaming/input/gamepad.cpp +++ b/app/streaming/input/gamepad.cpp @@ -6,6 +6,18 @@ #include +static bool isGamepadInputAllowed() +{ + auto session = Session::get(); + return session == nullptr || session->isGamepadInputAllowed(); +} + +static bool isKeyboardMouseInputAllowed() +{ + auto session = Session::get(); + return session == nullptr || session->isKeyboardMouseInputAllowed(); +} + // How long the Start button must be pressed to toggle mouse emulation #define MOUSE_EMULATION_LONG_PRESS_TIME 750 @@ -101,15 +113,17 @@ void SdlInputHandler::sendGamepadState(GamepadState* state) } } - LiSendMultiControllerEvent(state->index, - m_GamepadMask, - buttons, - lt, - rt, - lsX, - lsY, - rsX, - rsY); + if (isGamepadInputAllowed()) { + LiSendMultiControllerEvent(state->index, + m_GamepadMask, + buttons, + lt, + rt, + lsX, + lsY, + rsX, + rsY); + } } void SdlInputHandler::sendGamepadBatteryState(GamepadState* state, SDL_JoystickPowerLevel level) @@ -150,7 +164,9 @@ void SdlInputHandler::sendGamepadBatteryState(GamepadState* state, SDL_JoystickP return; } - LiSendControllerBatteryEvent(state->index, batteryState, batteryPercentage); + if (isGamepadInputAllowed()) { + LiSendControllerBatteryEvent(state->index, batteryState, batteryPercentage); + } } Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param) @@ -181,7 +197,7 @@ Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param deltaX = qAbs(deltaX) > MOUSE_EMULATION_DEADZONE ? deltaX - MOUSE_EMULATION_DEADZONE : 0; deltaY = qAbs(deltaY) > MOUSE_EMULATION_DEADZONE ? deltaY - MOUSE_EMULATION_DEADZONE : 0; - if (deltaX != 0 || deltaY != 0) { + if ((deltaX != 0 || deltaY != 0) && isKeyboardMouseInputAllowed()) { LiSendMouseMoveEvent((short)deltaX, (short)deltaY); } @@ -291,31 +307,49 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve } else if (state->mouseEmulationTimer != 0) { if (event->button == SDL_CONTROLLER_BUTTON_A) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); + } } else if (event->button == SDL_CONTROLLER_BUTTON_B) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + } } else if (event->button == SDL_CONTROLLER_BUTTON_X) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_MIDDLE); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_MIDDLE); + } } else if (event->button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X1); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X1); + } } else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X2); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X2); + } } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_UP) { - LiSendScrollEvent(1); + if (isKeyboardMouseInputAllowed()) { + LiSendScrollEvent(1); + } } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) { - LiSendScrollEvent(-1); + if (isKeyboardMouseInputAllowed()) { + LiSendScrollEvent(-1); + } } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) { - LiSendHScrollEvent(1); + if (isKeyboardMouseInputAllowed()) { + LiSendHScrollEvent(1); + } } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) { - LiSendHScrollEvent(-1); + if (isKeyboardMouseInputAllowed()) { + LiSendHScrollEvent(-1); + } } } } @@ -346,19 +380,29 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve } else if (state->mouseEmulationTimer != 0) { if (event->button == SDL_CONTROLLER_BUTTON_A) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + } } else if (event->button == SDL_CONTROLLER_BUTTON_B) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + } } else if (event->button == SDL_CONTROLLER_BUTTON_X) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_MIDDLE); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_MIDDLE); + } } else if (event->button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X1); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X1); + } } else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2); + } } } } @@ -375,8 +419,10 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve SDL_PushEvent(&event); // Clear buttons down on this gamepad - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); + if (isGamepadInputAllowed()) { + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); + } return; } @@ -390,8 +436,41 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve !Session::get()->getOverlayManager().isOverlayEnabled(Overlay::OverlayDebug)); // Clear buttons down on this gamepad - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); + if (isGamepadInputAllowed()) { + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); + } + return; + } + + if (state->buttons == (BACK_FLAG | LB_FLAG | RB_FLAG | Y_FLAG)) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected keyboard/mouse input toggle gamepad combo"); + + Session::get()->toggleKeyboardMouseInputAllowed(); + + if (isGamepadInputAllowed()) { + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); + } + return; + } + + if (state->buttons == (BACK_FLAG | LB_FLAG | RB_FLAG | A_FLAG)) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected gamepad input toggle gamepad combo"); + + bool gamepadWasEnabled = isGamepadInputAllowed(); + if (gamepadWasEnabled) { + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); + } + Session::get()->toggleGamepadInputAllowed(); + + if (isGamepadInputAllowed()) { + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); + } return; } @@ -418,7 +497,9 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve memcpy(state->lastAccelEventData, event->data, sizeof(event->data)); state->lastAccelEventTime = event->timestamp; - LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_ACCEL, event->data[0], event->data[1], event->data[2]); + if (isGamepadInputAllowed()) { + LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_ACCEL, event->data[0], event->data[1], event->data[2]); + } } break; case SDL_SENSOR_GYRO: @@ -429,10 +510,12 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve state->lastGyroEventTime = event->timestamp; // Convert rad/s to deg/s - LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_GYRO, - event->data[0] * 57.2957795f, - event->data[1] * 57.2957795f, - event->data[2] * 57.2957795f); + if (isGamepadInputAllowed()) { + LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_GYRO, + event->data[0] * 57.2957795f, + event->data[1] * 57.2957795f, + event->data[2] * 57.2957795f); + } } break; } @@ -460,7 +543,9 @@ void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* return; } - LiSendControllerTouchEvent((uint8_t)state->index, eventType, event->finger, event->x, event->y, event->pressure); + if (isGamepadInputAllowed()) { + LiSendControllerTouchEvent((uint8_t)state->index, eventType, event->finger, event->x, event->y, event->pressure); + } } #endif @@ -708,7 +793,9 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve #endif type == LI_CTYPE_PS; - LiSendControllerArrivalEvent(state->index, m_GamepadMask, type, supportedButtonFlags, capabilities); + if (isGamepadInputAllowed()) { + LiSendControllerArrivalEvent(state->index, m_GamepadMask, type, supportedButtonFlags, capabilities); + } #else // Send an empty event to tell the PC we've arrived @@ -750,8 +837,10 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve state->index); // Send a final event to let the PC know this gamepad is gone - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); + if (isGamepadInputAllowed()) { + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); + } // Clear all remaining state from this slot SDL_memset(state, 0, sizeof(*state)); diff --git a/app/streaming/input/input.cpp b/app/streaming/input/input.cpp index 982eaaa9..844e0ab4 100644 --- a/app/streaming/input/input.cpp +++ b/app/streaming/input/input.cpp @@ -106,6 +106,16 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i m_SpecialKeyCombos[KeyComboPasteText].scanCode = SDL_SCANCODE_V; m_SpecialKeyCombos[KeyComboPasteText].enabled = true; + m_SpecialKeyCombos[KeyComboToggleKeyboardMouseInput].keyCombo = KeyComboToggleKeyboardMouseInput; + m_SpecialKeyCombos[KeyComboToggleKeyboardMouseInput].keyCode = SDLK_k; + m_SpecialKeyCombos[KeyComboToggleKeyboardMouseInput].scanCode = SDL_SCANCODE_K; + m_SpecialKeyCombos[KeyComboToggleKeyboardMouseInput].enabled = true; + + m_SpecialKeyCombos[KeyComboToggleGamepadInput].keyCombo = KeyComboToggleGamepadInput; + m_SpecialKeyCombos[KeyComboToggleGamepadInput].keyCode = SDLK_g; + m_SpecialKeyCombos[KeyComboToggleGamepadInput].scanCode = SDL_SCANCODE_G; + m_SpecialKeyCombos[KeyComboToggleGamepadInput].enabled = true; + m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCombo = KeyComboTogglePointerRegionLock; m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCode = SDLK_l; m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].scanCode = SDL_SCANCODE_L; diff --git a/app/streaming/input/input.h b/app/streaming/input/input.h index 20bbbc33..91a020ce 100644 --- a/app/streaming/input/input.h +++ b/app/streaming/input/input.h @@ -165,6 +165,8 @@ private: KeyComboToggleCursorHide, KeyComboToggleMinimize, KeyComboPasteText, + KeyComboToggleKeyboardMouseInput, + KeyComboToggleGamepadInput, KeyComboTogglePointerRegionLock, KeyComboQuitAndExit, KeyComboMax diff --git a/app/streaming/input/keyboard.cpp b/app/streaming/input/keyboard.cpp index 273816f4..819837c0 100644 --- a/app/streaming/input/keyboard.cpp +++ b/app/streaming/input/keyboard.cpp @@ -13,6 +13,12 @@ #define VK_NUMPAD0 0x60 #endif +static bool isKeyboardMouseInputAllowed() +{ + auto session = Session::get(); + return session == nullptr || session->isKeyboardMouseInputAllowed(); +} + void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) { switch (combo) { @@ -114,7 +120,9 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) } // Send this text to the PC - LiSendUtf8TextEvent(text, (unsigned int)strlen(text)); + if (isKeyboardMouseInputAllowed()) { + LiSendUtf8TextEvent(text, (unsigned int)strlen(text)); + } // SDL_GetClipboardText() allocates, so we must free SDL_free((void*)text); @@ -126,6 +134,22 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) break; } + case KeyComboToggleKeyboardMouseInput: + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected keyboard/mouse input toggle combo"); + if (auto session = Session::get(); session != nullptr) { + session->toggleKeyboardMouseInputAllowed(); + } + break; + + case KeyComboToggleGamepadInput: + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected gamepad input toggle combo"); + if (auto session = Session::get(); session != nullptr) { + session->toggleGamepadInputAllowed(); + } + break; + case KeyComboTogglePointerRegionLock: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected pointer region lock toggle combo"); @@ -457,9 +481,11 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event) m_KeysDown.remove(keyCode); } - LiSendKeyboardEvent2(0x8000 | keyCode, - event->state == SDL_PRESSED ? - KEY_ACTION_DOWN : KEY_ACTION_UP, - modifiers, - shouldNotConvertToScanCodeOnServer ? SS_KBE_FLAG_NON_NORMALIZED : 0); + if (isKeyboardMouseInputAllowed()) { + LiSendKeyboardEvent2(0x8000 | keyCode, + event->state == SDL_PRESSED ? + KEY_ACTION_DOWN : KEY_ACTION_UP, + modifiers, + shouldNotConvertToScanCodeOnServer ? SS_KBE_FLAG_NON_NORMALIZED : 0); + } } diff --git a/app/streaming/input/mouse.cpp b/app/streaming/input/mouse.cpp index 66bb4413..c86eae54 100644 --- a/app/streaming/input/mouse.cpp +++ b/app/streaming/input/mouse.cpp @@ -1,9 +1,16 @@ #include "input.h" +#include "streaming/session.h" #include #include "SDL_compat.h" #include "streaming/streamutils.h" +static bool isKeyboardMouseInputAllowed() +{ + auto session = Session::get(); + return session == nullptr || session->isKeyboardMouseInputAllowed(); +} + void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event) { int button; @@ -62,10 +69,12 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event) button = BUTTON_RIGHT; } - LiSendMouseButtonEvent(event->state == SDL_PRESSED ? - BUTTON_ACTION_PRESS : - BUTTON_ACTION_RELEASE, - button); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(event->state == SDL_PRESSED ? + BUTTON_ACTION_PRESS : + BUTTON_ACTION_RELEASE, + button); + } } void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) @@ -134,7 +143,9 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) } } if (mouseInVideoRegion || m_MouseWasInVideoRegion || m_PendingMouseButtonsAllUpOnVideoRegionLeave) { - LiSendMousePositionEvent((short)x, (short)y, dst.w, dst.h); + if (isKeyboardMouseInputAllowed()) { + LiSendMousePositionEvent((short)x, (short)y, dst.w, dst.h); + } } // Adjust the cursor visibility if applicable @@ -150,7 +161,9 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) m_MouseWasInVideoRegion = mouseInVideoRegion; } else { - LiSendMouseMoveEvent(xrel, yrel); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseMoveEvent(xrel, yrel); + } } } @@ -187,7 +200,9 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->preciseY = SDL_clamp(event->preciseY, -1.0f, 1.0f); #endif - LiSendHighResScrollEvent((short)(event->preciseY * 120)); // WHEEL_DELTA + if (isKeyboardMouseInputAllowed()) { + LiSendHighResScrollEvent((short)(event->preciseY * 120)); // WHEEL_DELTA + } } if (event->preciseX != 0.0f) { @@ -202,7 +217,9 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->preciseX = SDL_clamp(event->preciseX, -1.0f, 1.0f); #endif - LiSendHighResHScrollEvent((short)(event->preciseX * 120)); // WHEEL_DELTA + if (isKeyboardMouseInputAllowed()) { + LiSendHighResHScrollEvent((short)(event->preciseX * 120)); // WHEEL_DELTA + } } #else if (event->y != 0) { @@ -216,7 +233,9 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->y = SDL_clamp(event->y, -1, 1); #endif - LiSendScrollEvent((signed char)event->y); + if (isKeyboardMouseInputAllowed()) { + LiSendScrollEvent((signed char)event->y); + } } if (event->x != 0) { @@ -230,7 +249,9 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->x = SDL_clamp(event->x, -1, 1); #endif - LiSendHScrollEvent((signed char)event->x); + if (isKeyboardMouseInputAllowed()) { + LiSendHScrollEvent((signed char)event->x); + } } #endif } diff --git a/app/streaming/input/reltouch.cpp b/app/streaming/input/reltouch.cpp index 0ddc778a..1649f1c1 100644 --- a/app/streaming/input/reltouch.cpp +++ b/app/streaming/input/reltouch.cpp @@ -1,10 +1,17 @@ #include "input.h" +#include "streaming/session.h" #include #include "SDL_compat.h" #include +static bool isKeyboardMouseInputAllowed() +{ + auto session = Session::get(); + return session == nullptr || session->isKeyboardMouseInputAllowed(); +} + // How long the mouse button will be pressed for a tap to click gesture #define TAP_BUTTON_RELEASE_DELAY 100 @@ -16,13 +23,17 @@ Uint32 SdlInputHandler::releaseLeftButtonTimerCallback(Uint32, void*) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + } return 0; } Uint32 SdlInputHandler::releaseRightButtonTimerCallback(Uint32, void*) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + } return 0; } @@ -39,7 +50,9 @@ Uint32 SdlInputHandler::dragTimerCallback(Uint32, void *param) me->m_DragButton = BUTTON_LEFT; } - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, me->m_DragButton); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, me->m_DragButton); + } return 0; } @@ -99,7 +112,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) // than the client window dimensions. short deltaX = static_cast(event->dx * m_StreamWidth); short deltaY = static_cast(event->dy * m_StreamHeight); - if (deltaX != 0 || deltaY != 0) { + if ((deltaX != 0 || deltaY != 0) && isKeyboardMouseInputAllowed()) { LiSendMouseMoveEvent(deltaX, deltaY); } } @@ -133,7 +146,9 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) // Release any drag if (m_DragButton != 0) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, m_DragButton); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, m_DragButton); + } m_DragButton = 0; } // 2 finger tap @@ -143,7 +158,9 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) m_TouchDownEvent[0].timestamp = 0; // Press down the right mouse button - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + } // Queue a timer to release it in 100 ms SDL_RemoveTimer(m_RightButtonReleaseTimer); @@ -154,7 +171,9 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) // 1 finger tap else if (event->timestamp - m_TouchDownEvent[0].timestamp < 250) { // Press down the left mouse button - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); + if (isKeyboardMouseInputAllowed()) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); + } // Queue a timer to release it in 100 ms SDL_RemoveTimer(m_LeftButtonReleaseTimer); diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index ad3741b0..c314ae83 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -556,6 +556,8 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere m_VideoDecoder(nullptr), m_DecoderLock(SDL_CreateMutex()), m_AudioMuted(false), + m_AllowGamepadInput(true), + m_AllowKeyboardMouseInput(true), m_QtWindow(nullptr), m_UnexpectedTermination(true), // Failure prior to streaming is unexpected m_InputHandler(nullptr), @@ -571,6 +573,45 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere { } +void Session::setGamepadInputAllowed(bool allowed) +{ + m_AllowGamepadInput.store(allowed, std::memory_order_relaxed); + notifyInputPermissionState(); +} + +void Session::setKeyboardMouseInputAllowed(bool allowed) +{ + bool previous = m_AllowKeyboardMouseInput.exchange(allowed, std::memory_order_relaxed); + if (previous && !allowed && m_InputHandler != nullptr) { + m_InputHandler->raiseAllKeys(); + } + + notifyInputPermissionState(); +} + +void Session::toggleGamepadInputAllowed() +{ + setGamepadInputAllowed(!isGamepadInputAllowed()); +} + +void Session::toggleKeyboardMouseInputAllowed() +{ + setKeyboardMouseInputAllowed(!isKeyboardMouseInputAllowed()); +} + +void Session::notifyInputPermissionState() +{ + char buffer[96]; + SDL_snprintf(buffer, + sizeof(buffer), + "Keyboard/Mouse: %s\nGamepad: %s", + isKeyboardMouseInputAllowed() ? "ON" : "OFF", + isGamepadInputAllowed() ? "ON" : "OFF"); + + m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, buffer); + m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true); +} + Session::~Session() { // NB: This may not get destroyed for a long time! Don't put any non-trivial cleanup here. diff --git a/app/streaming/session.h b/app/streaming/session.h index b4bba36d..d232bdbc 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -125,6 +126,22 @@ public: void setShouldExit(bool quitHostApp = false); + bool isGamepadInputAllowed() const + { + return m_AllowGamepadInput.load(std::memory_order_relaxed); + } + + bool isKeyboardMouseInputAllowed() const + { + return m_AllowKeyboardMouseInput.load(std::memory_order_relaxed); + } + + void setGamepadInputAllowed(bool allowed); + void setKeyboardMouseInputAllowed(bool allowed); + void toggleGamepadInputAllowed(); + void toggleKeyboardMouseInputAllowed(); + void notifyInputPermissionState(); + signals: void stageStarting(QString stage); @@ -255,6 +272,8 @@ private: SDL_mutex* m_DecoderLock; bool m_AudioDisabled; bool m_AudioMuted; + std::atomic m_AllowGamepadInput; + std::atomic m_AllowKeyboardMouseInput; Uint32 m_FullScreenFlag; QQuickWindow* m_QtWindow; bool m_UnexpectedTermination;