diff --git a/.gitignore b/.gitignore index c41d075f..3a5180ac 100644 --- a/.gitignore +++ b/.gitignore @@ -4,30 +4,5 @@ **/.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 diff --git a/.gitmodules b/.gitmodules index b40a0fa8..42c2f1a7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "moonlight-common-c/moonlight-common-c"] path = moonlight-common-c/moonlight-common-c - url = git.joeypayne.com:jyapayne/moonlight-common-c + url = https://github.com/moonlight-stream/moonlight-common-c.git [submodule "qmdnsengine/qmdnsengine"] path = qmdnsengine/qmdnsengine url = https://github.com/cgutman/qmdnsengine.git diff --git a/app/app.pro b/app/app.pro index 717c753e..9fb043dd 100644 --- a/app/app.pro +++ b/app/app.pro @@ -179,7 +179,6 @@ SOURCES += \ settings/streamingpreferences.cpp \ streaming/input/abstouch.cpp \ streaming/input/gamepad.cpp \ - streaming/input/sdlinputsubsystems.cpp \ streaming/input/input.cpp \ streaming/input/keyboard.cpp \ streaming/input/mouse.cpp \ @@ -220,7 +219,6 @@ HEADERS += \ cli/quitstream.h \ cli/startstream.h \ settings/streamingpreferences.h \ - streaming/input/sdlinputsubsystems.h \ streaming/input/input.h \ streaming/session.h \ streaming/audio/renderers/renderer.h \ diff --git a/app/gui/sdlgamepadkeynavigation.cpp b/app/gui/sdlgamepadkeynavigation.cpp index 21d44e09..d35a70b6 100644 --- a/app/gui/sdlgamepadkeynavigation.cpp +++ b/app/gui/sdlgamepadkeynavigation.cpp @@ -4,27 +4,10 @@ #include #include -#include "streaming/input/sdlinputsubsystems.h" +#include "settings/mappingmanager.h" #define AXIS_NAVIGATION_REPEAT_DELAY 150 -namespace { - -SdlInputSubsystems::LeaseOptions guiNavSubsystemLeaseOptions() -{ - SdlInputSubsystems::LeaseOptions options = {}; - options.joystick = true; - options.gameController = true; -#if !SDL_VERSION_ATLEAST(2, 0, 9) - options.haptic = false; -#endif - options.applyMappings = true; - options.flushControllerDeviceEvents = true; - return options; -} - -} - SdlGamepadKeyNavigation::SdlGamepadKeyNavigation(StreamingPreferences* prefs) : m_Prefs(prefs), m_Enabled(false), @@ -48,13 +31,32 @@ void SdlGamepadKeyNavigation::enable() return; } - if (!SdlInputSubsystems::acquire("GuiGamepadNavigation", guiNavSubsystemLeaseOptions())) { + // We have to initialize and uninitialize this in enable()/disable() + // because we need to get out of the way of the Session class. If it + // doesn't get to reinitialize the GC subsystem, it won't get initial + // arrival events. Additionally, there's a race condition between + // our QML objects being destroyed and SDL being deinitialized that + // this solves too. + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to acquire SDL input subsystems for GUI gamepad navigation"); + "SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s", + SDL_GetError()); return; } + MappingManager mappingManager; + mappingManager.applyMappings(); + + // Drop all pending gamepad add events. SDL will generate these for us + // on first init of the GC subsystem. We can't depend on them due to + // overlapping lifetimes of SdlGamepadKeyNavigation instances, so we + // will attach ourselves. + // + // NB: We use SDL_JoystickUpdate() instead of SDL_PumpEvents() because + // the latter can do a bit more work that we want (like handling video + // events that we intentionally do not want to process yet). SDL_JoystickUpdate(); + SDL_FlushEvent(SDL_CONTROLLERDEVICEADDED); // Open all currently attached game controllers int numJoysticks = SDL_NumJoysticks(); @@ -88,7 +90,7 @@ void SdlGamepadKeyNavigation::disable() m_Gamepads.removeAt(0); } - SdlInputSubsystems::release("GuiGamepadNavigation", guiNavSubsystemLeaseOptions()); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); } void SdlGamepadKeyNavigation::notifyWindowFocus(bool hasFocus) diff --git a/app/streaming/audio/audio.cpp b/app/streaming/audio/audio.cpp index 2cbec50b..4668eec9 100644 --- a/app/streaming/audio/audio.cpp +++ b/app/streaming/audio/audio.cpp @@ -8,7 +8,6 @@ #include "renderers/sdl.h" #include -#include #define TRY_INIT_RENDERER(renderer, opusConfig) \ { \ @@ -184,7 +183,7 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength) s_ActiveSession->m_AudioSampleCount++; // If audio is muted, don't decode or play the audio - if (s_ActiveSession->m_AudioMuted.load(std::memory_order_relaxed)) { + if (s_ActiveSession->m_AudioMuted) { return; } @@ -218,27 +217,6 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength) if (samplesDecoded > 0) { SDL_assert(desiredBufferSize >= frameSize * samplesDecoded); desiredBufferSize = frameSize * samplesDecoded; - - const float volume = s_ActiveSession->getAudioVolumeScalar(); - if (volume <= 0.0f) { - SDL_memset(buffer, 0, desiredBufferSize); - } - else if (volume < 1.0f) { - const int totalSamples = samplesDecoded * s_ActiveSession->m_ActiveAudioConfig.channelCount; - if (s_ActiveSession->m_AudioRenderer->getAudioBufferFormat() == IAudioRenderer::AudioFormat::Float32NE) { - float* output = (float*)buffer; - for (int i = 0; i < totalSamples; i++) { - output[i] = SDL_clamp(output[i] * volume, -1.0f, 1.0f); - } - } - else { - short* output = (short*)buffer; - for (int i = 0; i < totalSamples; i++) { - const int scaled = (int) std::lround((float)output[i] * volume); - output[i] = (short)SDL_clamp(scaled, -32768, 32767); - } - } - } } else { desiredBufferSize = 0; diff --git a/app/streaming/input/abstouch.cpp b/app/streaming/input/abstouch.cpp index 6c8529a2..0fe6dac6 100644 --- a/app/streaming/input/abstouch.cpp +++ b/app/streaming/input/abstouch.cpp @@ -1,5 +1,4 @@ #include "input.h" -#include "streaming/session.h" #include #include "SDL_compat.h" @@ -8,12 +7,6 @@ #include -static bool isKeyboardMouseInputAllowed() -{ - auto session = Session::get(); - return session == nullptr || session->isMouseInputAllowed(); -} - // How long the fingers must be stationary to start a right click #define LONG_PRESS_ACTIVATION_DELAY 650 @@ -29,10 +22,8 @@ static bool isKeyboardMouseInputAllowed() Uint32 SdlInputHandler::longPressTimerCallback(Uint32, void*) { // Raise the left click and start a right click - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); return 0; } @@ -119,7 +110,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 (isKeyboardMouseInputAllowed() && (LiGetHostFeatureFlags() & LI_FF_PEN_TOUCH_EVENTS)) { + if (LiGetHostFeatureFlags() & LI_FF_PEN_TOUCH_EVENTS) { #if SDL_VERSION_ATLEAST(2, 0, 22) bool isPen = false; @@ -206,9 +197,7 @@ 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 - if (isKeyboardMouseInputAllowed()) { - LiSendMousePositionEvent(x - dst.x, y - dst.y, dst.w, dst.h); - } + LiSendMousePositionEvent(x - dst.x, y - dst.y, dst.w, dst.h); } if (event->type == SDL_FINGERDOWN) { @@ -221,9 +210,7 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event) nullptr); // Left button down on finger down - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); } else if (event->type == SDL_FINGERUP) { m_LastTouchUpEvent = *event; @@ -233,13 +220,9 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event) m_LongPressTimer = 0; // Left button up on finger up - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); // Raise right button too in case we triggered a long press gesture - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); } } diff --git a/app/streaming/input/gamepad.cpp b/app/streaming/input/gamepad.cpp index 6d5601a4..e0d7f004 100644 --- a/app/streaming/input/gamepad.cpp +++ b/app/streaming/input/gamepad.cpp @@ -2,33 +2,16 @@ #include #include "SDL_compat.h" -#include "streaming/input/sdlinputsubsystems.h" +#include "settings/mappingmanager.h" #include -static bool isGamepadInputAllowed() -{ - auto session = Session::get(); - return session == nullptr || session->isGamepadInputAllowed(); -} - -static bool isMouseInputAllowed() -{ - auto session = Session::get(); - return session == nullptr || session->isMouseInputAllowed(); -} - // How long the Start button must be pressed to toggle mouse emulation #define MOUSE_EMULATION_LONG_PRESS_TIME 750 // How long between polling the gamepad to send virtual mouse input #define MOUSE_EMULATION_POLLING_INTERVAL 50 -#define HOTPLUG_REENUMERATION_INTERVAL_MS 2000 -#define HOTPLUG_REENUMERATION_MAX_INTERVAL_MS 8000 -#define HOTPLUG_REENUMERATION_MIN_ZERO_POLLS 4 -#define HOTPLUG_REENUMERATION_MIN_LAST_SEEN_MS 500 - // Determines how fast the mouse will move each interval #define MOUSE_EMULATION_MOTION_MULTIPLIER 4 @@ -57,7 +40,7 @@ SdlInputHandler::findStateForGamepad(SDL_JoystickID id) int i; for (i = 0; i < MAX_GAMEPADS; i++) { - if (m_GamepadState[i].controller != nullptr && m_GamepadState[i].jsId == id) { + if (m_GamepadState[i].jsId == id) { SDL_assert(!m_MultiController || m_GamepadState[i].index == i); return &m_GamepadState[i]; } @@ -68,191 +51,6 @@ SdlInputHandler::findStateForGamepad(SDL_JoystickID id) return nullptr; } -GamepadState* -SdlInputHandler::ensureStateForGamepad(SDL_JoystickID id) -{ - GamepadState* state = findStateForGamepad(id); - if (state != nullptr) { - return state; - } - - cleanupDetachedGamepads(); - - const int joystickCount = SDL_NumJoysticks(); - for (int deviceIndex = 0; deviceIndex < joystickCount; deviceIndex++) { - if (!SDL_IsGameController(deviceIndex)) { - continue; - } - - if (SDL_JoystickGetDeviceInstanceID(deviceIndex) != id) { - continue; - } - - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Recovering gamepad state for missing add event (instance ID: %d)", - id); - - SDL_ControllerDeviceEvent controllerEvent = {}; - controllerEvent.type = SDL_CONTROLLERDEVICEADDED; - controllerEvent.which = deviceIndex; - handleControllerDeviceEvent(&controllerEvent); - break; - } - - return findStateForGamepad(id); -} - -void SdlInputHandler::pollForMissingGamepads() -{ - static uint32_t s_LastForcedReenumerationTick = 0; - static uint32_t s_ReenumerationIntervalMs = HOTPLUG_REENUMERATION_INTERVAL_MS; - static uint32_t s_ReenumerationAttempts = 0; - static uint32_t s_ConsecutiveZeroPolls = 0; - - SDL_JoystickUpdate(); - SDL_GameControllerUpdate(); - - uint32_t now = SDL_GetTicks(); - - auto recoverUntrackedGamepads = [this](int joystickCount) { - for (int deviceIndex = 0; deviceIndex < joystickCount; deviceIndex++) { - if (!SDL_IsGameController(deviceIndex)) { - continue; - } - - SDL_JoystickID jsId = SDL_JoystickGetDeviceInstanceID(deviceIndex); - if (jsId < 0 || findStateForGamepad(jsId) != nullptr) { - continue; - } - - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Polling recovered missing gamepad add event (device index: %d, instance ID: %d)", - deviceIndex, - jsId); - - SDL_ControllerDeviceEvent controllerEvent = {}; - controllerEvent.type = SDL_CONTROLLERDEVICEADDED; - controllerEvent.which = deviceIndex; - handleControllerDeviceEvent(&controllerEvent); - } - }; - - int joystickCount = SDL_NumJoysticks(); - if (joystickCount != m_LastJoystickCount) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected joystick count change: %d -> %d", - m_LastJoystickCount, - joystickCount); - m_LastJoystickCount = joystickCount; - } - - if (joystickCount > 0) { - m_LastNonZeroJoystickTick = now; - s_ConsecutiveZeroPolls = 0; - s_ReenumerationAttempts = 0; - s_ReenumerationIntervalMs = HOTPLUG_REENUMERATION_INTERVAL_MS; - } - else { - s_ConsecutiveZeroPolls++; - } - - for (int i = 0; i < MAX_GAMEPADS; i++) { - GamepadState* state = &m_GamepadState[i]; - if (state->controller == nullptr) { - continue; - } - - bool presentInDeviceList = false; - for (int deviceIndex = 0; deviceIndex < joystickCount; deviceIndex++) { - if (SDL_JoystickGetDeviceInstanceID(deviceIndex) == state->jsId) { - presentInDeviceList = true; - break; - } - } - - if (presentInDeviceList) { - continue; - } - - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Polling detected disconnected gamepad instance %d in slot %d; cleaning up", - state->jsId, - i); - - SDL_ControllerDeviceEvent controllerEvent = {}; - controllerEvent.type = SDL_CONTROLLERDEVICEREMOVED; - controllerEvent.which = state->jsId; - handleControllerDeviceEvent(&controllerEvent); - } - - recoverUntrackedGamepads(joystickCount); - - bool shouldAttemptReenumeration = - joystickCount == 0 && - m_LastNonZeroJoystickTick != 0 && - s_ConsecutiveZeroPolls >= HOTPLUG_REENUMERATION_MIN_ZERO_POLLS && - SDL_TICKS_PASSED(now, m_LastNonZeroJoystickTick + HOTPLUG_REENUMERATION_MIN_LAST_SEEN_MS); - - if (shouldAttemptReenumeration) { - if (SDL_TICKS_PASSED(now, s_LastForcedReenumerationTick + s_ReenumerationIntervalMs)) { - s_LastForcedReenumerationTick = now; - s_ReenumerationAttempts++; - - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "No joysticks visible after reconciliation; forcing last-resort SDL re-enumeration (attempt %u, interval %u ms)", - s_ReenumerationAttempts, - s_ReenumerationIntervalMs); - - if (SdlInputSubsystems::reenumerateGamepadSubsystems("StreamInputHotplug")) { - joystickCount = SDL_NumJoysticks(); - if (joystickCount != m_LastJoystickCount) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected joystick count change after re-enumeration: %d -> %d", - m_LastJoystickCount, - joystickCount); - m_LastJoystickCount = joystickCount; - } - - recoverUntrackedGamepads(joystickCount); - - if (joystickCount > 0) { - m_LastNonZeroJoystickTick = now; - s_ConsecutiveZeroPolls = 0; - s_ReenumerationAttempts = 0; - s_ReenumerationIntervalMs = HOTPLUG_REENUMERATION_INTERVAL_MS; - } - else { - s_ReenumerationIntervalMs = qMin(s_ReenumerationIntervalMs * 2, - static_cast(HOTPLUG_REENUMERATION_MAX_INTERVAL_MS)); - } - } - else { - s_ReenumerationIntervalMs = qMin(s_ReenumerationIntervalMs * 2, - static_cast(HOTPLUG_REENUMERATION_MAX_INTERVAL_MS)); - } - } - } -} - -void SdlInputHandler::cleanupDetachedGamepads() -{ - for (int i = 0; i < MAX_GAMEPADS; i++) { - if (m_GamepadState[i].controller == nullptr || - SDL_GameControllerGetAttached(m_GamepadState[i].controller)) { - continue; - } - - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Found detached gamepad in slot %d without removal event; cleaning up", - i); - - SDL_ControllerDeviceEvent controllerEvent = {}; - controllerEvent.type = SDL_CONTROLLERDEVICEREMOVED; - controllerEvent.which = m_GamepadState[i].jsId; - handleControllerDeviceEvent(&controllerEvent); - } -} - void SdlInputHandler::sendGamepadState(GamepadState* state) { SDL_assert(m_GamepadMask == 0x1 || m_MultiController); @@ -303,17 +101,15 @@ void SdlInputHandler::sendGamepadState(GamepadState* state) } } - if (isGamepadInputAllowed()) { - LiSendMultiControllerEvent(state->index, - m_GamepadMask, - buttons, - lt, - rt, - lsX, - lsY, - rsX, - rsY); - } + LiSendMultiControllerEvent(state->index, + m_GamepadMask, + buttons, + lt, + rt, + lsX, + lsY, + rsX, + rsY); } void SdlInputHandler::sendGamepadBatteryState(GamepadState* state, SDL_JoystickPowerLevel level) @@ -354,9 +150,7 @@ void SdlInputHandler::sendGamepadBatteryState(GamepadState* state, SDL_JoystickP return; } - if (isGamepadInputAllowed()) { - LiSendControllerBatteryEvent(state->index, batteryState, batteryPercentage); - } + LiSendControllerBatteryEvent(state->index, batteryState, batteryPercentage); } Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param) @@ -387,7 +181,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) && isMouseInputAllowed()) { + if (deltaX != 0 || deltaY != 0) { LiSendMouseMoveEvent((short)deltaX, (short)deltaY); } @@ -397,7 +191,7 @@ Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event) { SDL_JoystickID gameControllerId = event->which; - GamepadState* state = ensureStateForGamepad(gameControllerId); + GamepadState* state = findStateForGamepad(gameControllerId); if (state == NULL) { return; } @@ -467,7 +261,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve return; } - GamepadState* state = ensureStateForGamepad(event->which); + GamepadState* state = findStateForGamepad(event->which); if (state == NULL) { return; } @@ -497,49 +291,31 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve } else if (state->mouseEmulationTimer != 0) { if (event->button == SDL_CONTROLLER_BUTTON_A) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); } else if (event->button == SDL_CONTROLLER_BUTTON_B) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); } else if (event->button == SDL_CONTROLLER_BUTTON_X) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_MIDDLE); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_MIDDLE); } else if (event->button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X1); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X1); } else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X2); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X2); } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_UP) { - if (isMouseInputAllowed()) { - LiSendScrollEvent(1); - } + LiSendScrollEvent(1); } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) { - if (isMouseInputAllowed()) { - LiSendScrollEvent(-1); - } + LiSendScrollEvent(-1); } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) { - if (isMouseInputAllowed()) { - LiSendHScrollEvent(1); - } + LiSendHScrollEvent(1); } else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) { - if (isMouseInputAllowed()) { - LiSendHScrollEvent(-1); - } + LiSendHScrollEvent(-1); } } } @@ -570,29 +346,19 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve } else if (state->mouseEmulationTimer != 0) { if (event->button == SDL_CONTROLLER_BUTTON_A) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); } else if (event->button == SDL_CONTROLLER_BUTTON_B) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); } else if (event->button == SDL_CONTROLLER_BUTTON_X) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_MIDDLE); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_MIDDLE); } else if (event->button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X1); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X1); } else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { - if (isMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2); } } } @@ -609,10 +375,8 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve SDL_PushEvent(&event); // Clear buttons down on this gamepad - if (isGamepadInputAllowed()) { - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); - } + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); return; } @@ -626,67 +390,8 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve !Session::get()->getOverlayManager().isOverlayEnabled(Overlay::OverlayDebug)); // Clear buttons down on this gamepad - if (isGamepadInputAllowed()) { - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); - } - return; - } - - if (state->buttons == (BACK_FLAG | LB_FLAG | RB_FLAG | B_FLAG)) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected control panel toggle gamepad combo"); - - Session::get()->toggleControlPanelVisibility(); - - 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 input toggle gamepad combo"); - - Session::get()->toggleKeyboardInputAllowed(); - - if (isGamepadInputAllowed()) { - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); - } - return; - } - - if (state->buttons == (BACK_FLAG | LB_FLAG | RB_FLAG | UP_FLAG)) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected mouse input toggle gamepad combo"); - - Session::get()->toggleMouseInputAllowed(); - - 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); - } + LiSendMultiControllerEvent(state->index, m_GamepadMask, + 0, 0, 0, 0, 0, 0, 0); return; } @@ -700,7 +405,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* event) { - GamepadState* state = ensureStateForGamepad(event->which); + GamepadState* state = findStateForGamepad(event->which); if (state == NULL) { return; } @@ -713,9 +418,7 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve memcpy(state->lastAccelEventData, event->data, sizeof(event->data)); state->lastAccelEventTime = event->timestamp; - if (isGamepadInputAllowed()) { - LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_ACCEL, event->data[0], event->data[1], event->data[2]); - } + LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_ACCEL, event->data[0], event->data[1], event->data[2]); } break; case SDL_SENSOR_GYRO: @@ -726,12 +429,10 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve state->lastGyroEventTime = event->timestamp; // Convert rad/s to deg/s - 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); - } + 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; } @@ -739,7 +440,7 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event) { - GamepadState* state = ensureStateForGamepad(event->which); + GamepadState* state = findStateForGamepad(event->which); if (state == NULL) { return; } @@ -759,9 +460,7 @@ void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* return; } - if (isGamepadInputAllowed()) { - LiSendControllerTouchEvent((uint8_t)state->index, eventType, event->finger, event->x, event->y, event->pressure); - } + LiSendControllerTouchEvent((uint8_t)state->index, eventType, event->finger, event->x, event->y, event->pressure); } #endif @@ -770,7 +469,7 @@ void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* void SdlInputHandler::handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event) { - GamepadState* state = ensureStateForGamepad(event->which); + GamepadState* state = findStateForGamepad(event->which); if (state == NULL) { return; } @@ -785,8 +484,6 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve GamepadState* state; if (event->type == SDL_CONTROLLERDEVICEADDED) { - cleanupDetachedGamepads(); - int i; const char* name; SDL_GameController* controller; @@ -802,17 +499,15 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve return; } - SDL_JoystickID jsId = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller)); - // SDL_CONTROLLERDEVICEADDED can be reported multiple times for the same // gamepad in rare cases, because SDL doesn't fixup the device index in // the SDL_CONTROLLERDEVICEADDED event if an unopened gamepad disappears // before we've processed the add event. for (int i = 0; i < MAX_GAMEPADS; i++) { - if (m_GamepadState[i].controller != nullptr && m_GamepadState[i].jsId == jsId) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Received duplicate add event for joystick instance ID: %d", - jsId); + if (m_GamepadState[i].controller == controller) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Received duplicate add event for controller index: %d", + event->which); SDL_GameControllerClose(controller); return; } @@ -868,7 +563,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve } state->controller = controller; - state->jsId = jsId; + state->jsId = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(state->controller)); hapticCaps = 0; #if SDL_VERSION_ATLEAST(2, 0, 18) @@ -1013,9 +708,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve #endif type == LI_CTYPE_PS; - if (isGamepadInputAllowed()) { - LiSendControllerArrivalEvent(state->index, m_GamepadMask, type, supportedButtonFlags, capabilities); - } + LiSendControllerArrivalEvent(state->index, m_GamepadMask, type, supportedButtonFlags, capabilities); #else // Send an empty event to tell the PC we've arrived @@ -1057,10 +750,8 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve state->index); // Send a final event to let the PC know this gamepad is gone - if (isGamepadInputAllowed()) { - LiSendMultiControllerEvent(state->index, m_GamepadMask, - 0, 0, 0, 0, 0, 0, 0); - } + 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)); @@ -1072,49 +763,29 @@ void SdlInputHandler::handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event) { SDL_assert(event->type == SDL_JOYDEVICEADDED); - if (SDL_IsGameController(event->which)) { - SDL_ControllerDeviceEvent controllerEvent = {}; - controllerEvent.type = SDL_CONTROLLERDEVICEADDED; - controllerEvent.which = event->which; - handleControllerDeviceEvent(&controllerEvent); - return; - } - - char guidStr[33]; - SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(event->which), - guidStr, sizeof(guidStr)); - const char* name = SDL_JoystickNameForIndex(event->which); - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Joystick discovered with no mapping: %s %s", - name ? name : "", - guidStr); - SDL_Joystick* joy = SDL_JoystickOpen(event->which); - if (joy != nullptr) { + if (!SDL_IsGameController(event->which)) { + char guidStr[33]; + SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(event->which), + guidStr, sizeof(guidStr)); + const char* name = SDL_JoystickNameForIndex(event->which); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Number of axes: %d | Number of buttons: %d | Number of hats: %d", - SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), - SDL_JoystickNumHats(joy)); - SDL_JoystickClose(joy); + "Joystick discovered with no mapping: %s %s", + name ? name : "", + guidStr); + SDL_Joystick* joy = SDL_JoystickOpen(event->which); + if (joy != nullptr) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Number of axes: %d | Number of buttons: %d | Number of hats: %d", + SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), + SDL_JoystickNumHats(joy)); + SDL_JoystickClose(joy); + } + else { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Unable to open joystick for query: %s", + SDL_GetError()); + } } - else { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Unable to open joystick for query: %s", - SDL_GetError()); - } -} - -void SdlInputHandler::handleJoystickRemovalEvent(SDL_JoyDeviceEvent* event) -{ - SDL_assert(event->type == SDL_JOYDEVICEREMOVED); - - if (findStateForGamepad(event->which) == nullptr) { - return; - } - - SDL_ControllerDeviceEvent controllerEvent = {}; - controllerEvent.type = SDL_CONTROLLERDEVICEREMOVED; - controllerEvent.which = event->which; - handleControllerDeviceEvent(&controllerEvent); } void SdlInputHandler::rumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor) @@ -1249,21 +920,15 @@ QString SdlInputHandler::getUnmappedGamepads() { QString ret; - SdlInputSubsystems::LeaseOptions options = {}; - options.joystick = true; - options.gameController = true; -#if !SDL_VERSION_ATLEAST(2, 0, 9) - options.haptic = false; -#endif - options.applyMappings = true; - options.flushControllerDeviceEvents = false; - - if (!SdlInputSubsystems::acquire("UnmappedGamepadProbe", options)) { + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to acquire SDL input subsystems for unmapped gamepad probe"); - return ret; + "SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s", + SDL_GetError()); } + MappingManager mappingManager; + mappingManager.applyMappings(); + int numJoysticks = SDL_NumJoysticks(); for (int i = 0; i < numJoysticks; i++) { if (!SDL_IsGameController(i)) { @@ -1305,7 +970,7 @@ QString SdlInputHandler::getUnmappedGamepads() } } - SdlInputSubsystems::release("UnmappedGamepadProbe", options); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); // Flush stale events so they aren't processed by the main session event loop SDL_FlushEvents(SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED); diff --git a/app/streaming/input/input.cpp b/app/streaming/input/input.cpp index 39a230a5..982eaaa9 100644 --- a/app/streaming/input/input.cpp +++ b/app/streaming/input/input.cpp @@ -1,7 +1,7 @@ #include #include "SDL_compat.h" #include "streaming/session.h" -#include "streaming/input/sdlinputsubsystems.h" +#include "settings/mappingmanager.h" #include "path.h" #include "utils.h" @@ -9,23 +9,6 @@ #include #include -namespace { - -SdlInputSubsystems::LeaseOptions streamInputSubsystemLeaseOptions() -{ - SdlInputSubsystems::LeaseOptions options = {}; - options.joystick = true; - options.gameController = true; -#if !SDL_VERSION_ATLEAST(2, 0, 9) - options.haptic = true; -#endif - options.applyMappings = true; - options.flushControllerDeviceEvents = true; - return options; -} - -} - SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, int streamHeight) : m_MultiController(prefs.multiController), m_GamepadMouse(prefs.gamepadMouse), @@ -36,8 +19,6 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i m_PendingMouseButtonsAllUpOnVideoRegionLeave(false), m_PointerRegionLockActive(false), m_PointerRegionLockToggledByUser(false), - m_LastJoystickCount(-1), - m_LastNonZeroJoystickTick(0), m_FakeCaptureActive(false), m_CaptureSystemKeysMode(prefs.captureSysKeysMode), m_MouseCursorCapturedVisibilityState(SDL_DISABLE), @@ -105,11 +86,6 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i m_SpecialKeyCombos[KeyComboToggleStatsOverlay].scanCode = SDL_SCANCODE_S; m_SpecialKeyCombos[KeyComboToggleStatsOverlay].enabled = true; - m_SpecialKeyCombos[KeyComboToggleControlPanel].keyCombo = KeyComboToggleControlPanel; - m_SpecialKeyCombos[KeyComboToggleControlPanel].keyCode = SDLK_p; - m_SpecialKeyCombos[KeyComboToggleControlPanel].scanCode = SDL_SCANCODE_P; - m_SpecialKeyCombos[KeyComboToggleControlPanel].enabled = true; - m_SpecialKeyCombos[KeyComboToggleMouseMode].keyCombo = KeyComboToggleMouseMode; m_SpecialKeyCombos[KeyComboToggleMouseMode].keyCode = SDLK_m; m_SpecialKeyCombos[KeyComboToggleMouseMode].scanCode = SDL_SCANCODE_M; @@ -130,36 +106,6 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i m_SpecialKeyCombos[KeyComboPasteText].scanCode = SDL_SCANCODE_V; m_SpecialKeyCombos[KeyComboPasteText].enabled = true; - m_SpecialKeyCombos[KeyComboToggleKeyboardInput].keyCombo = KeyComboToggleKeyboardInput; - m_SpecialKeyCombos[KeyComboToggleKeyboardInput].keyCode = SDLK_k; - m_SpecialKeyCombos[KeyComboToggleKeyboardInput].scanCode = SDL_SCANCODE_K; - m_SpecialKeyCombos[KeyComboToggleKeyboardInput].enabled = true; - - m_SpecialKeyCombos[KeyComboToggleMouseInput].keyCombo = KeyComboToggleMouseInput; - m_SpecialKeyCombos[KeyComboToggleMouseInput].keyCode = SDLK_o; - m_SpecialKeyCombos[KeyComboToggleMouseInput].scanCode = SDL_SCANCODE_O; - m_SpecialKeyCombos[KeyComboToggleMouseInput].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[KeyComboVolumeUp].keyCombo = KeyComboVolumeUp; - m_SpecialKeyCombos[KeyComboVolumeUp].keyCode = SDLK_u; - m_SpecialKeyCombos[KeyComboVolumeUp].scanCode = SDL_SCANCODE_U; - m_SpecialKeyCombos[KeyComboVolumeUp].enabled = true; - - m_SpecialKeyCombos[KeyComboVolumeDown].keyCombo = KeyComboVolumeDown; - m_SpecialKeyCombos[KeyComboVolumeDown].keyCode = SDLK_j; - m_SpecialKeyCombos[KeyComboVolumeDown].scanCode = SDL_SCANCODE_J; - m_SpecialKeyCombos[KeyComboVolumeDown].enabled = true; - - m_SpecialKeyCombos[KeyComboToggleMute].keyCombo = KeyComboToggleMute; - m_SpecialKeyCombos[KeyComboToggleMute].keyCode = SDLK_n; - m_SpecialKeyCombos[KeyComboToggleMute].scanCode = SDL_SCANCODE_N; - m_SpecialKeyCombos[KeyComboToggleMute].enabled = true; - m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCombo = KeyComboTogglePointerRegionLock; m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCode = SDLK_l; m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].scanCode = SDL_SCANCODE_L; @@ -201,11 +147,45 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i SDL_SetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES, streamIgnoreDevices.toUtf8()); SDL_SetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, streamIgnoreDevicesExcept.toUtf8()); - if (!SdlInputSubsystems::acquire("StreamInput", streamInputSubsystemLeaseOptions())) { + // We must initialize joystick explicitly before gamecontroller in order + // to ensure we receive gamecontroller attach events for gamepads where + // SDL doesn't have a built-in mapping. By starting joystick first, we + // can allow mapping manager to update the mappings before GC attach + // events are generated. + SDL_assert(!SDL_WasInit(SDL_INIT_JOYSTICK)); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to acquire SDL input subsystems for streaming input"); + "SDL_InitSubSystem(SDL_INIT_JOYSTICK) failed: %s", + SDL_GetError()); } + MappingManager mappingManager; + mappingManager.applyMappings(); + + // Flush gamepad arrival and departure events which may be queued before + // starting the gamecontroller subsystem again. This prevents us from + // receiving duplicate arrival and departure events for the same gamepad. + SDL_FlushEvent(SDL_CONTROLLERDEVICEADDED); + SDL_FlushEvent(SDL_CONTROLLERDEVICEREMOVED); + + // We need to reinit this each time, since you only get + // an initial set of gamepad arrival events once per init. + SDL_assert(!SDL_WasInit(SDL_INIT_GAMECONTROLLER)); + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s", + SDL_GetError()); + } + +#if !SDL_VERSION_ATLEAST(2, 0, 9) + SDL_assert(!SDL_WasInit(SDL_INIT_HAPTIC)); + if (SDL_InitSubSystem(SDL_INIT_HAPTIC) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_InitSubSystem(SDL_INIT_HAPTIC) failed: %s", + SDL_GetError()); + } +#endif + // Initialize the gamepad mask with currently attached gamepads to avoid // causing gamepads to unexpectedly disappear and reappear on the host // during stream startup as we detect currently attached gamepads one at a time. @@ -239,7 +219,16 @@ SdlInputHandler::~SdlInputHandler() SDL_RemoveTimer(m_RightButtonReleaseTimer); SDL_RemoveTimer(m_DragTimer); - SdlInputSubsystems::release("StreamInput", streamInputSubsystemLeaseOptions()); +#if !SDL_VERSION_ATLEAST(2, 0, 9) + SDL_QuitSubSystem(SDL_INIT_HAPTIC); + SDL_assert(!SDL_WasInit(SDL_INIT_HAPTIC)); +#endif + + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + SDL_assert(!SDL_WasInit(SDL_INIT_GAMECONTROLLER)); + + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_assert(!SDL_WasInit(SDL_INIT_JOYSTICK)); // Return background event handling to off SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "0"); @@ -279,50 +268,6 @@ void SdlInputHandler::raiseAllKeys() m_KeysDown.clear(); } -void SdlInputHandler::raiseAllMouseButtons() -{ - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_MIDDLE); - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X1); - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2); -} - -void SdlInputHandler::raiseAllGamepadInputs() -{ - uint16_t raisedIndexMask = 0; - - for (auto &state : m_GamepadState) { - if (state.controller == nullptr) { - continue; - } - - state.buttons = 0; - state.lt = 0; - state.rt = 0; - state.lsX = 0; - state.lsY = 0; - state.rsX = 0; - state.rsY = 0; - state.emulatedClickpadButtonDown = false; - - if ((raisedIndexMask & (1 << state.index)) != 0) { - continue; - } - - LiSendMultiControllerEvent(state.index, - m_GamepadMask, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - raisedIndexMask |= (1 << state.index); - } -} - void SdlInputHandler::notifyMouseLeave() { // SDL on Windows doesn't send the mouse button up until the mouse re-enters the window diff --git a/app/streaming/input/input.h b/app/streaming/input/input.h index 46e3ae79..20bbbc33 100644 --- a/app/streaming/input/input.h +++ b/app/streaming/input/input.h @@ -116,10 +116,6 @@ public: void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event); - void handleJoystickRemovalEvent(SDL_JoyDeviceEvent* event); - - void pollForMissingGamepads(); - void sendText(QString& string); void rumble(uint16_t controllerNumber, uint16_t lowFreqMotor, uint16_t highFreqMotor); @@ -138,10 +134,6 @@ public: void raiseAllKeys(); - void raiseAllMouseButtons(); - - void raiseAllGamepadInputs(); - void notifyMouseLeave(); void notifyFocusLost(); @@ -169,17 +161,10 @@ private: KeyComboUngrabInput, KeyComboToggleFullScreen, KeyComboToggleStatsOverlay, - KeyComboToggleControlPanel, KeyComboToggleMouseMode, KeyComboToggleCursorHide, KeyComboToggleMinimize, KeyComboPasteText, - KeyComboToggleKeyboardInput, - KeyComboToggleMouseInput, - KeyComboToggleGamepadInput, - KeyComboVolumeUp, - KeyComboVolumeDown, - KeyComboToggleMute, KeyComboTogglePointerRegionLock, KeyComboQuitAndExit, KeyComboMax @@ -188,11 +173,6 @@ private: GamepadState* findStateForGamepad(SDL_JoystickID id); - GamepadState* - ensureStateForGamepad(SDL_JoystickID id); - - void cleanupDetachedGamepads(); - void sendGamepadState(GamepadState* state); void sendGamepadBatteryState(GamepadState* state, SDL_JoystickPowerLevel level); @@ -235,8 +215,6 @@ private: bool m_PointerRegionLockToggledByUser; int m_GamepadMask; - int m_LastJoystickCount; - uint32_t m_LastNonZeroJoystickTick; GamepadState m_GamepadState[MAX_GAMEPADS]; QSet m_KeysDown; bool m_FakeCaptureActive; diff --git a/app/streaming/input/keyboard.cpp b/app/streaming/input/keyboard.cpp index ede74d51..273816f4 100644 --- a/app/streaming/input/keyboard.cpp +++ b/app/streaming/input/keyboard.cpp @@ -13,12 +13,6 @@ #define VK_NUMPAD0 0x60 #endif -static bool isKeyboardMouseInputAllowed() -{ - auto session = Session::get(); - return session == nullptr || session->isKeyboardInputAllowed(); -} - void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) { switch (combo) { @@ -64,14 +58,6 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) !Session::get()->getOverlayManager().isOverlayEnabled(Overlay::OverlayDebug)); break; - case KeyComboToggleControlPanel: - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected control panel toggle combo"); - if (auto session = Session::get(); session != nullptr) { - session->toggleControlPanelVisibility(); - } - break; - case KeyComboToggleMouseMode: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected mouse mode toggle combo"); @@ -128,9 +114,7 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) } // Send this text to the PC - if (isKeyboardMouseInputAllowed()) { - LiSendUtf8TextEvent(text, (unsigned int)strlen(text)); - } + LiSendUtf8TextEvent(text, (unsigned int)strlen(text)); // SDL_GetClipboardText() allocates, so we must free SDL_free((void*)text); @@ -142,54 +126,6 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo) break; } - case KeyComboToggleKeyboardInput: - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected keyboard input toggle combo"); - if (auto session = Session::get(); session != nullptr) { - session->toggleKeyboardInputAllowed(); - } - break; - - case KeyComboToggleMouseInput: - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected mouse input toggle combo"); - if (auto session = Session::get(); session != nullptr) { - session->toggleMouseInputAllowed(); - } - 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 KeyComboVolumeUp: - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected volume up combo"); - if (auto session = Session::get(); session != nullptr) { - session->adjustAudioVolume(0.05f); - } - break; - - case KeyComboVolumeDown: - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected volume down combo"); - if (auto session = Session::get(); session != nullptr) { - session->adjustAudioVolume(-0.05f); - } - break; - - case KeyComboToggleMute: - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Detected audio mute toggle combo"); - if (auto session = Session::get(); session != nullptr) { - session->toggleAudioMute(); - } - break; - case KeyComboTogglePointerRegionLock: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected pointer region lock toggle combo"); @@ -521,11 +457,9 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event) m_KeysDown.remove(keyCode); } - if (isKeyboardMouseInputAllowed()) { - LiSendKeyboardEvent2(0x8000 | keyCode, - event->state == SDL_PRESSED ? - KEY_ACTION_DOWN : KEY_ACTION_UP, - modifiers, - shouldNotConvertToScanCodeOnServer ? SS_KBE_FLAG_NON_NORMALIZED : 0); - } + 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 d452ed07..66bb4413 100644 --- a/app/streaming/input/mouse.cpp +++ b/app/streaming/input/mouse.cpp @@ -1,16 +1,9 @@ #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->isMouseInputAllowed(); -} - void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event) { int button; @@ -69,12 +62,10 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event) button = BUTTON_RIGHT; } - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(event->state == SDL_PRESSED ? - BUTTON_ACTION_PRESS : - BUTTON_ACTION_RELEASE, - button); - } + LiSendMouseButtonEvent(event->state == SDL_PRESSED ? + BUTTON_ACTION_PRESS : + BUTTON_ACTION_RELEASE, + button); } void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) @@ -143,9 +134,7 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) } } if (mouseInVideoRegion || m_MouseWasInVideoRegion || m_PendingMouseButtonsAllUpOnVideoRegionLeave) { - if (isKeyboardMouseInputAllowed()) { - LiSendMousePositionEvent((short)x, (short)y, dst.w, dst.h); - } + LiSendMousePositionEvent((short)x, (short)y, dst.w, dst.h); } // Adjust the cursor visibility if applicable @@ -161,9 +150,7 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event) m_MouseWasInVideoRegion = mouseInVideoRegion; } else { - if (isKeyboardMouseInputAllowed()) { - LiSendMouseMoveEvent(xrel, yrel); - } + LiSendMouseMoveEvent(xrel, yrel); } } @@ -200,9 +187,7 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->preciseY = SDL_clamp(event->preciseY, -1.0f, 1.0f); #endif - if (isKeyboardMouseInputAllowed()) { - LiSendHighResScrollEvent((short)(event->preciseY * 120)); // WHEEL_DELTA - } + LiSendHighResScrollEvent((short)(event->preciseY * 120)); // WHEEL_DELTA } if (event->preciseX != 0.0f) { @@ -217,9 +202,7 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->preciseX = SDL_clamp(event->preciseX, -1.0f, 1.0f); #endif - if (isKeyboardMouseInputAllowed()) { - LiSendHighResHScrollEvent((short)(event->preciseX * 120)); // WHEEL_DELTA - } + LiSendHighResHScrollEvent((short)(event->preciseX * 120)); // WHEEL_DELTA } #else if (event->y != 0) { @@ -233,9 +216,7 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->y = SDL_clamp(event->y, -1, 1); #endif - if (isKeyboardMouseInputAllowed()) { - LiSendScrollEvent((signed char)event->y); - } + LiSendScrollEvent((signed char)event->y); } if (event->x != 0) { @@ -249,9 +230,7 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) event->x = SDL_clamp(event->x, -1, 1); #endif - if (isKeyboardMouseInputAllowed()) { - LiSendHScrollEvent((signed char)event->x); - } + LiSendHScrollEvent((signed char)event->x); } #endif } diff --git a/app/streaming/input/reltouch.cpp b/app/streaming/input/reltouch.cpp index 6269537f..0ddc778a 100644 --- a/app/streaming/input/reltouch.cpp +++ b/app/streaming/input/reltouch.cpp @@ -1,17 +1,10 @@ #include "input.h" -#include "streaming/session.h" #include #include "SDL_compat.h" #include -static bool isKeyboardMouseInputAllowed() -{ - auto session = Session::get(); - return session == nullptr || session->isMouseInputAllowed(); -} - // How long the mouse button will be pressed for a tap to click gesture #define TAP_BUTTON_RELEASE_DELAY 100 @@ -23,17 +16,13 @@ static bool isKeyboardMouseInputAllowed() Uint32 SdlInputHandler::releaseLeftButtonTimerCallback(Uint32, void*) { - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); return 0; } Uint32 SdlInputHandler::releaseRightButtonTimerCallback(Uint32, void*) { - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); return 0; } @@ -50,9 +39,7 @@ Uint32 SdlInputHandler::dragTimerCallback(Uint32, void *param) me->m_DragButton = BUTTON_LEFT; } - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, me->m_DragButton); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, me->m_DragButton); return 0; } @@ -112,7 +99,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) && isKeyboardMouseInputAllowed()) { + if (deltaX != 0 || deltaY != 0) { LiSendMouseMoveEvent(deltaX, deltaY); } } @@ -146,9 +133,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) // Release any drag if (m_DragButton != 0) { - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, m_DragButton); - } + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, m_DragButton); m_DragButton = 0; } // 2 finger tap @@ -158,9 +143,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) m_TouchDownEvent[0].timestamp = 0; // Press down the right mouse button - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); // Queue a timer to release it in 100 ms SDL_RemoveTimer(m_RightButtonReleaseTimer); @@ -171,9 +154,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event) // 1 finger tap else if (event->timestamp - m_TouchDownEvent[0].timestamp < 250) { // Press down the left mouse button - if (isKeyboardMouseInputAllowed()) { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); - } + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); // Queue a timer to release it in 100 ms SDL_RemoveTimer(m_LeftButtonReleaseTimer); diff --git a/app/streaming/input/sdlinputsubsystems.cpp b/app/streaming/input/sdlinputsubsystems.cpp deleted file mode 100644 index bb1d3646..00000000 --- a/app/streaming/input/sdlinputsubsystems.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "streaming/input/sdlinputsubsystems.h" - -#include "settings/mappingmanager.h" - -namespace { - -int s_JoystickRefs = 0; -int s_GameControllerRefs = 0; -#if !SDL_VERSION_ATLEAST(2, 0, 9) -int s_HapticRefs = 0; -#endif - -bool retainSubsystem(Uint32 subsystem, int& refs, const char* subsystemName, const char* ownerTag) -{ - if (refs == 0 && SDL_InitSubSystem(subsystem) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to initialize %s subsystem for %s: %s", - subsystemName, - ownerTag, - SDL_GetError()); - return false; - } - - refs++; - return true; -} - -void releaseSubsystem(Uint32 subsystem, int& refs, const char* subsystemName, const char* ownerTag) -{ - if (refs <= 0) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Ignoring unbalanced release of %s subsystem for %s", - subsystemName, - ownerTag); - refs = 0; - return; - } - - refs--; - if (refs == 0) { - SDL_QuitSubSystem(subsystem); - } -} - -} - -namespace SdlInputSubsystems { - -bool acquire(const char* ownerTag, const LeaseOptions& options) -{ - bool acquiredJoystick = false; -#if !SDL_VERSION_ATLEAST(2, 0, 9) - bool acquiredGameController = false; - bool acquiredHaptic = false; -#endif - - if (options.joystick) { - if (!retainSubsystem(SDL_INIT_JOYSTICK, s_JoystickRefs, "joystick", ownerTag)) { - return false; - } - acquiredJoystick = true; - } - - if (options.gameController) { - if (!retainSubsystem(SDL_INIT_GAMECONTROLLER, s_GameControllerRefs, "gamecontroller", ownerTag)) { - if (acquiredJoystick) { - releaseSubsystem(SDL_INIT_JOYSTICK, s_JoystickRefs, "joystick", ownerTag); - } - return false; - } -#if !SDL_VERSION_ATLEAST(2, 0, 9) - acquiredGameController = true; -#endif - } - -#if !SDL_VERSION_ATLEAST(2, 0, 9) - if (options.haptic) { - if (!retainSubsystem(SDL_INIT_HAPTIC, s_HapticRefs, "haptic", ownerTag)) { - if (acquiredGameController) { - releaseSubsystem(SDL_INIT_GAMECONTROLLER, s_GameControllerRefs, "gamecontroller", ownerTag); - } - if (acquiredJoystick) { - releaseSubsystem(SDL_INIT_JOYSTICK, s_JoystickRefs, "joystick", ownerTag); - } - return false; - } - acquiredHaptic = true; - } -#endif - - if (options.applyMappings) { - MappingManager mappingManager; - mappingManager.applyMappings(); - } - - if (options.flushControllerDeviceEvents) { - SDL_FlushEvent(SDL_CONTROLLERDEVICEADDED); - SDL_FlushEvent(SDL_CONTROLLERDEVICEREMOVED); - } - - return true; -} - -void release(const char* ownerTag, const LeaseOptions& options) -{ -#if !SDL_VERSION_ATLEAST(2, 0, 9) - if (options.haptic) { - releaseSubsystem(SDL_INIT_HAPTIC, s_HapticRefs, "haptic", ownerTag); - } -#endif - - if (options.gameController) { - releaseSubsystem(SDL_INIT_GAMECONTROLLER, s_GameControllerRefs, "gamecontroller", ownerTag); - } - - if (options.joystick) { - releaseSubsystem(SDL_INIT_JOYSTICK, s_JoystickRefs, "joystick", ownerTag); - } -} - -bool hasExclusiveGamepadOwnership() -{ - if (s_JoystickRefs != 1 || s_GameControllerRefs != 1) { - return false; - } - -#if !SDL_VERSION_ATLEAST(2, 0, 9) - if (s_HapticRefs != 1) { - return false; - } -#endif - - return true; -} - -bool reenumerateGamepadSubsystems(const char* ownerTag) -{ - if (!hasExclusiveGamepadOwnership()) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Skipping subsystem re-enumeration for %s due to shared ownership (joystick=%d gamecontroller=%d)", - ownerTag, - s_JoystickRefs, - s_GameControllerRefs); - return false; - } - -#if !SDL_VERSION_ATLEAST(2, 0, 9) - SDL_QuitSubSystem(SDL_INIT_HAPTIC); -#endif - SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to reinitialize joystick subsystem for %s: %s", - ownerTag, - SDL_GetError()); - return false; - } - - if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to reinitialize gamecontroller subsystem for %s: %s", - ownerTag, - SDL_GetError()); - return false; - } - -#if !SDL_VERSION_ATLEAST(2, 0, 9) - if (SDL_InitSubSystem(SDL_INIT_HAPTIC) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to reinitialize haptic subsystem for %s: %s", - ownerTag, - SDL_GetError()); - return false; - } -#endif - - MappingManager mappingManager; - mappingManager.applyMappings(); - - SDL_JoystickUpdate(); - SDL_GameControllerUpdate(); - - SDL_FlushEvents(SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED); - SDL_FlushEvents(SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMAPPED); - - return true; -} - -} diff --git a/app/streaming/input/sdlinputsubsystems.h b/app/streaming/input/sdlinputsubsystems.h deleted file mode 100644 index c5e4e3c5..00000000 --- a/app/streaming/input/sdlinputsubsystems.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "SDL_compat.h" - -namespace SdlInputSubsystems { - -struct LeaseOptions { - bool joystick; - bool gameController; -#if !SDL_VERSION_ATLEAST(2, 0, 9) - bool haptic; -#endif - bool applyMappings; - bool flushControllerDeviceEvents; -}; - -bool acquire(const char* ownerTag, const LeaseOptions& options); - -void release(const char* ownerTag, const LeaseOptions& options); - -bool hasExclusiveGamepadOwnership(); - -bool reenumerateGamepadSubsystems(const char* ownerTag); - -} diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 01aa4800..ad3741b0 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -28,8 +28,6 @@ #define SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE 103 #define SDL_CODE_GAMECONTROLLER_SET_CONTROLLER_LED 104 #define SDL_CODE_GAMECONTROLLER_SET_ADAPTIVE_TRIGGERS 105 -#define SDL_CODE_HIDE_STATUS_OVERLAY 106 -#define SDL_CODE_SET_INPUT_POLICY 107 #include @@ -62,8 +60,7 @@ CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = { Session::clRumbleTriggers, Session::clSetMotionEventState, Session::clSetControllerLED, - Session::clSetAdaptiveTriggers, - Session::clSetInputPolicy + Session::clSetAdaptiveTriggers }; Session* Session::s_ActiveSession; @@ -178,8 +175,27 @@ void Session::clConnectionStatusUpdate(int connectionStatus) "Connection status update: %d", connectionStatus); - s_ActiveSession->m_ConnectionStatus.store(connectionStatus, std::memory_order_relaxed); - s_ActiveSession->refreshControlPanelOverlay(); + if (!s_ActiveSession->m_Preferences->connectionWarnings) { + return; + } + + if (s_ActiveSession->m_MouseEmulationRefCount > 0) { + // Don't display the overlay if mouse emulation is already using it + return; + } + + switch (connectionStatus) + { + case CONN_STATUS_POOR: + s_ActiveSession->m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, + s_ActiveSession->m_StreamConfig.bitrate > 5000 ? + "Slow connection to PC\nReduce your bitrate" : "Poor connection to PC"); + s_ActiveSession->m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true); + break; + case CONN_STATUS_OKAY: + s_ActiveSession->m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false); + break; + } } void Session::clSetHdrMode(bool enabled) @@ -258,20 +274,6 @@ void Session::clSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlag SDL_PushEvent(&setControllerLEDEvent); } -void Session::clSetInputPolicy(uint8_t allowKeyboard, uint8_t allowMouse, uint8_t allowGamepad, uint8_t reason) -{ - SDL_Event setInputPolicyEvent = {}; - setInputPolicyEvent.type = SDL_USEREVENT; - setInputPolicyEvent.user.code = SDL_CODE_SET_INPUT_POLICY; - setInputPolicyEvent.user.data1 = nullptr; - setInputPolicyEvent.user.data2 = (void*)(uintptr_t)( - ((uintptr_t)allowKeyboard << 24) | - ((uintptr_t)allowMouse << 16) | - ((uintptr_t)allowGamepad << 8) | - (uintptr_t)reason); - SDL_PushEvent(&setInputPolicyEvent); -} - bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, SDL_Window* window, int videoFormat, int width, int height, @@ -554,14 +556,6 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere m_VideoDecoder(nullptr), m_DecoderLock(SDL_CreateMutex()), m_AudioMuted(false), - m_ManualAudioMuted(false), - m_AudioVolumeScalar(1.0f), - m_AllowGamepadInput(true), - m_AllowKeyboardInput(false), - m_AllowMouseInput(false), - m_ControlPanelVisible(true), - m_ConnectionStatus(CONN_STATUS_OKAY), - m_StatusOverlayGeneration(0), m_QtWindow(nullptr), m_UnexpectedTermination(true), // Failure prior to streaming is unexpected m_InputHandler(nullptr), @@ -575,285 +569,6 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere m_AudioSampleCount(0), m_DropAudioEndTime(0) { - m_TemporaryStatusOverlayText[0] = '\0'; -} - -void Session::setGamepadInputAllowed(bool allowed) -{ - if (!allowed && m_InputHandler != nullptr) { - m_InputHandler->raiseAllGamepadInputs(); - } - - m_AllowGamepadInput.store(allowed, std::memory_order_relaxed); - sendInputPermissionStateToHost(LI_SESSION_INPUT_POLICY_REASON_USER_TOGGLE); - notifyInputPermissionState(); -} - -void Session::setKeyboardInputAllowed(bool allowed) -{ - const bool previous = m_AllowKeyboardInput.exchange(allowed, std::memory_order_relaxed); - if (previous && !allowed && m_InputHandler != nullptr) { - m_InputHandler->raiseAllKeys(); - } - - sendInputPermissionStateToHost(LI_SESSION_INPUT_POLICY_REASON_USER_TOGGLE); - notifyInputPermissionState(); -} - -void Session::setMouseInputAllowed(bool allowed) -{ - const bool previous = m_AllowMouseInput.exchange(allowed, std::memory_order_relaxed); - if (previous && !allowed && m_InputHandler != nullptr) { - m_InputHandler->raiseAllMouseButtons(); - } - - sendInputPermissionStateToHost(LI_SESSION_INPUT_POLICY_REASON_USER_TOGGLE); - notifyInputPermissionState(); -} - -void Session::setAudioVolumeScalar(float scalar) -{ - scalar = SDL_clamp(scalar, 0.0f, 1.0f); - m_AudioVolumeScalar.store(scalar, std::memory_order_relaxed); - notifyAudioVolumeState(); -} - -void Session::adjustAudioVolume(float delta) -{ - const float current = getAudioVolumeScalar(); - const float next = SDL_clamp(current + delta, 0.0f, 1.0f); - setAudioVolumeScalar(next); -} - -void Session::toggleAudioMute() -{ - const bool muted = !m_ManualAudioMuted.load(std::memory_order_relaxed); - m_ManualAudioMuted.store(muted, std::memory_order_relaxed); - - updateEffectiveAudioMuteState(); - notifyAudioVolumeState(); -} - -void Session::notifyAudioVolumeState() -{ - char buffer[64]; - if (m_ManualAudioMuted.load(std::memory_order_relaxed)) { - SDL_snprintf(buffer, sizeof(buffer), "Volume: MUTED"); - } - else { - const int percent = (int)SDL_roundf(getAudioVolumeScalar() * 100.0f); - SDL_snprintf(buffer, sizeof(buffer), "Volume: %d%%", percent); - } - - showTemporaryStatusOverlay(buffer); -} - -void Session::setKeyboardMouseInputAllowed(bool allowed) -{ - const bool previousKeyboard = m_AllowKeyboardInput.exchange(allowed, std::memory_order_relaxed); - if (previousKeyboard && !allowed && m_InputHandler != nullptr) { - m_InputHandler->raiseAllKeys(); - } - - const bool previousMouse = m_AllowMouseInput.exchange(allowed, std::memory_order_relaxed); - if (previousMouse && !allowed && m_InputHandler != nullptr) { - m_InputHandler->raiseAllMouseButtons(); - } - - sendInputPermissionStateToHost(LI_SESSION_INPUT_POLICY_REASON_USER_TOGGLE); - notifyInputPermissionState(); -} - -void Session::toggleGamepadInputAllowed() -{ - setGamepadInputAllowed(!isGamepadInputAllowed()); -} - -void Session::toggleKeyboardInputAllowed() -{ - setKeyboardInputAllowed(!isKeyboardInputAllowed()); -} - -void Session::toggleMouseInputAllowed() -{ - setMouseInputAllowed(!isMouseInputAllowed()); -} - -void Session::toggleKeyboardMouseInputAllowed() -{ - setKeyboardMouseInputAllowed(!isKeyboardMouseInputAllowed()); -} - -void Session::toggleControlPanelVisibility() -{ - const bool visible = !m_ControlPanelVisible.load(std::memory_order_relaxed); - m_ControlPanelVisible.store(visible, std::memory_order_relaxed); - showTemporaryStatusOverlay(visible ? "Control panel shown" : "Control panel hidden"); -} - -void Session::notifyInputPermissionState() -{ - char buffer[160]; - SDL_snprintf(buffer, - sizeof(buffer), - "Input policy: host controlled\nKeyboard: %s\nMouse: %s\nGamepad: %s", - isKeyboardInputAllowed() ? "ON" : "OFF", - isMouseInputAllowed() ? "ON" : "OFF", - isGamepadInputAllowed() ? "ON" : "OFF"); - - showTemporaryStatusOverlay(buffer); -} - -void Session::sendInputPermissionStateToHost(uint8_t reason) -{ - const bool allowKeyboard = isKeyboardInputAllowed(); - const bool allowMouse = isMouseInputAllowed(); - const bool allowGamepad = isGamepadInputAllowed(); - const int err = LiSendSessionInputPolicy(allowKeyboard, - allowMouse, - allowGamepad, - reason); - - if (err != 0 && err != LI_ERR_UNSUPPORTED) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Failed to send input policy update to host: %d", - err); - } -} - -Uint32 Session::statusOverlayTimeoutCallback(Uint32, void* param) -{ - SDL_Event event = {}; - event.type = SDL_USEREVENT; - event.user.code = SDL_CODE_HIDE_STATUS_OVERLAY; - event.user.data1 = param; - SDL_PushEvent(&event); - - return 0; -} - -void Session::refreshControlPanelOverlay() -{ - if (!m_ControlPanelVisible.load(std::memory_order_relaxed)) { - if (m_TemporaryStatusOverlayText[0] != '\0') { - m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, m_TemporaryStatusOverlayText); - m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true); - } - else { - m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false); - } - return; - } - - char volumeState[24]; - if (m_ManualAudioMuted.load(std::memory_order_relaxed)) { - SDL_snprintf(volumeState, sizeof(volumeState), "MUTED"); - } - else { - const int percent = (int)SDL_roundf(getAudioVolumeScalar() * 100.0f); - SDL_snprintf(volumeState, sizeof(volumeState), "%d%%", percent); - } - - char panelText[640]; - SDL_snprintf(panelText, - sizeof(panelText), - "Stream Controls\n" - "Keyboard: %s (KB: Ctrl+Alt+Shift+K, Pad: Select+L1+R1+Y)\n" - "Mouse: %s (KB: Ctrl+Alt+Shift+O, Pad: Select+L1+R1+DPad Up)\n" - "Pad: %s (KB: Ctrl+Alt+Shift+G, Pad: Select+L1+R1+A)\n" - "Vol: %s (KB: U/J, mute N; Pad: none)\n" - "UI: ON (KB: Ctrl+Alt+Shift+P, Pad: Select+L1+R1+B)\n" - "Input policy: host controlled", - isKeyboardInputAllowed() ? "ON" : "OFF", - isMouseInputAllowed() ? "ON" : "OFF", - isGamepadInputAllowed() ? "ON" : "OFF", - volumeState); - - size_t used = SDL_strlen(panelText); - if (used < sizeof(panelText) && m_MouseEmulationRefCount > 0) { - SDL_snprintf(panelText + used, - sizeof(panelText) - used, - "\nMouse mode: ACTIVE (hold Start to disable)"); - used = SDL_strlen(panelText); - } - - if (used < sizeof(panelText) && - m_Preferences->connectionWarnings && - m_ConnectionStatus.load(std::memory_order_relaxed) == CONN_STATUS_POOR) { - SDL_snprintf(panelText + used, - sizeof(panelText) - used, - "\nNetwork: %s", - m_StreamConfig.bitrate > 5000 ? "Slow (reduce bitrate)" : "Poor"); - used = SDL_strlen(panelText); - } - - if (used < sizeof(panelText) && m_TemporaryStatusOverlayText[0] != '\0') { - SDL_snprintf(panelText + used, - sizeof(panelText) - used, - "\nStatus: %s", - m_TemporaryStatusOverlayText); - } - - m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, panelText); - m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true); -} - -void Session::showTemporaryStatusOverlay(const char* text, Uint32 timeoutMs) -{ - if (text == nullptr || text[0] == '\0') { - return; - } - - SDL_snprintf(m_TemporaryStatusOverlayText, - sizeof(m_TemporaryStatusOverlayText), - "%s", - text); - refreshControlPanelOverlay(); - - const uint32_t generation = m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed) + 1; - SDL_AddTimer(timeoutMs, statusOverlayTimeoutCallback, (void*)(uintptr_t)generation); -} - -void Session::applyHostInputPolicy(bool allowKeyboard, bool allowMouse, bool allowGamepad, uint8_t reason) -{ - const bool previousKeyboard = m_AllowKeyboardInput.exchange(allowKeyboard, std::memory_order_relaxed); - if (previousKeyboard && !allowKeyboard && m_InputHandler != nullptr) { - m_InputHandler->raiseAllKeys(); - } - - const bool previousMouse = m_AllowMouseInput.exchange(allowMouse, std::memory_order_relaxed); - if (previousMouse && !allowMouse && m_InputHandler != nullptr) { - m_InputHandler->raiseAllMouseButtons(); - } - - const bool previousGamepad = m_AllowGamepadInput.exchange(allowGamepad, std::memory_order_relaxed); - if (previousGamepad && !allowGamepad && m_InputHandler != nullptr) { - m_InputHandler->raiseAllGamepadInputs(); - } - - const bool policyChanged = - previousKeyboard != allowKeyboard || - previousMouse != allowMouse || - previousGamepad != allowGamepad; - if (reason == LI_SESSION_INPUT_POLICY_REASON_STREAM_START || - reason == LI_SESSION_INPUT_POLICY_REASON_HOST_ACK || - reason == LI_SESSION_INPUT_POLICY_REASON_HOST_OVERRIDE || - !policyChanged) { - refreshControlPanelOverlay(); - } - else { - notifyInputPermissionState(); - } -} - -void Session::updateEffectiveAudioMuteState() -{ - bool muted = m_ManualAudioMuted.load(std::memory_order_relaxed); - if (!muted && m_Preferences->muteOnFocusLoss && m_Window != nullptr) { - muted = SDL_GetKeyboardFocus() != m_Window; - } - - m_AudioMuted.store(muted, std::memory_order_relaxed); } Session::~Session() @@ -1826,8 +1541,14 @@ void Session::notifyMouseEmulationMode(bool enabled) m_MouseEmulationRefCount += enabled ? 1 : -1; SDL_assert(m_MouseEmulationRefCount >= 0); - showTemporaryStatusOverlay(enabled ? "Gamepad mouse mode enabled" : "Gamepad mouse mode disabled"); - refreshControlPanelOverlay(); + // We re-use the status update overlay for mouse mode notification + if (m_MouseEmulationRefCount > 0) { + m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, "Gamepad mouse mode active\nLong press Start to deactivate"); + m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true); + } + else { + m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false); + } } class AsyncConnectionStartThread : public QThread @@ -2026,17 +1747,6 @@ void Session::start() // We're now active s_ActiveSession = this; - m_AllowGamepadInput.store(true, std::memory_order_relaxed); - m_AllowKeyboardInput.store(false, std::memory_order_relaxed); - m_AllowMouseInput.store(false, std::memory_order_relaxed); - m_ManualAudioMuted.store(false, std::memory_order_relaxed); - m_AudioMuted.store(false, std::memory_order_relaxed); - m_AudioVolumeScalar.store(1.0f, std::memory_order_relaxed); - m_ControlPanelVisible.store(true, std::memory_order_relaxed); - m_ConnectionStatus.store(CONN_STATUS_OKAY, std::memory_order_relaxed); - m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed); - m_TemporaryStatusOverlayText[0] = '\0'; - // Initialize the gamepad code with our preferences // NB: m_InputHandler must be initialize before starting the connection. m_InputHandler = new SdlInputHandler(*m_Preferences, m_StreamConfig.width, m_StreamConfig.height); @@ -2239,7 +1949,6 @@ void Session::exec() // Toggle the stats overlay if requested by the user m_OverlayManager.setOverlayState(Overlay::OverlayDebug, m_Preferences->showPerformanceOverlay); - refreshControlPanelOverlay(); // Switch to async logging mode when we enter the SDL loop StreamUtils::enterAsyncLoggingMode(); @@ -2247,14 +1956,7 @@ void Session::exec() // Hijack this thread to be the SDL main thread. We have to do this // because we want to suspend all Qt processing until the stream is over. SDL_Event event; - uint32_t nextGamepadPollTime = SDL_GetTicks(); for (;;) { - uint32_t now = SDL_GetTicks(); - if (SDL_TICKS_PASSED(now, nextGamepadPollTime)) { - m_InputHandler->pollForMissingGamepads(); - nextGamepadPollTime = now + 250; - } - #if SDL_VERSION_ATLEAST(2, 0, 18) && !defined(STEAM_LINK) // SDL 2.0.18 has a proper wait event implementation that uses platform // support to block on events rather than polling on Windows, macOS, X11, @@ -2266,7 +1968,6 @@ void Session::exec() // issues that could cause indefinite timeouts, delayed joystick detection, // and other problems. if (!SDL_WaitEventTimeout(&event, 1000)) { - updateEffectiveAudioMuteState(); presence.runCallbacks(); continue; } @@ -2283,14 +1984,10 @@ void Session::exec() // ARM core in the Steam Link, so we will wait 10 ms instead. SDL_Delay(10); #endif - updateEffectiveAudioMuteState(); presence.runCallbacks(); continue; } #endif - - updateEffectiveAudioMuteState(); - switch (event.type) { case SDL_QUIT: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, @@ -2332,21 +2029,6 @@ void Session::exec() m_InputHandler->setAdaptiveTriggers((uint16_t)(uintptr_t)event.user.data1, (DualSenseOutputReport *)event.user.data2); break; - case SDL_CODE_SET_INPUT_POLICY: { - const uintptr_t packed = (uintptr_t)event.user.data2; - const bool allowKeyboard = ((packed >> 24) & 0xFF) != 0; - const bool allowMouse = ((packed >> 16) & 0xFF) != 0; - const bool allowGamepad = ((packed >> 8) & 0xFF) != 0; - const uint8_t reason = (uint8_t)(packed & 0xFF); - applyHostInputPolicy(allowKeyboard, allowMouse, allowGamepad, reason); - break; - } - case SDL_CODE_HIDE_STATUS_OVERLAY: - if ((uint32_t)(uintptr_t)event.user.data1 == m_StatusOverlayGeneration.load(std::memory_order_relaxed)) { - m_TemporaryStatusOverlayText[0] = '\0'; - refreshControlPanelOverlay(); - } - break; default: SDL_assert(false); } @@ -2356,9 +2038,15 @@ void Session::exec() // Early handling of some events switch (event.window.event) { case SDL_WINDOWEVENT_FOCUS_LOST: + if (m_Preferences->muteOnFocusLoss) { + m_AudioMuted = true; + } m_InputHandler->notifyFocusLost(); break; case SDL_WINDOWEVENT_FOCUS_GAINED: + if (m_Preferences->muteOnFocusLoss) { + m_AudioMuted = false; + } m_InputHandler->notifyFocusGained(); break; case SDL_WINDOWEVENT_LEAVE: @@ -2545,7 +2233,6 @@ void Session::exec() // After a window resize, we need to reset the pointer lock region m_InputHandler->updatePointerRegionLock(); - refreshControlPanelOverlay(); SDL_UnlockMutex(m_DecoderLock); break; @@ -2596,9 +2283,6 @@ void Session::exec() case SDL_JOYDEVICEADDED: m_InputHandler->handleJoystickArrivalEvent(&event.jdevice); break; - case SDL_JOYDEVICEREMOVED: - m_InputHandler->handleJoystickRemovalEvent(&event.jdevice); - break; case SDL_FINGERDOWN: case SDL_FINGERMOTION: case SDL_FINGERUP: diff --git a/app/streaming/session.h b/app/streaming/session.h index 6289bf62..b4bba36d 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -126,47 +125,6 @@ public: void setShouldExit(bool quitHostApp = false); - bool isGamepadInputAllowed() const - { - return m_AllowGamepadInput.load(std::memory_order_relaxed); - } - - bool isKeyboardInputAllowed() const - { - return m_AllowKeyboardInput.load(std::memory_order_relaxed); - } - - bool isMouseInputAllowed() const - { - return m_AllowMouseInput.load(std::memory_order_relaxed); - } - - bool isKeyboardMouseInputAllowed() const - { - return isKeyboardInputAllowed() && isMouseInputAllowed(); - } - - void setGamepadInputAllowed(bool allowed); - void setKeyboardInputAllowed(bool allowed); - void setMouseInputAllowed(bool allowed); - void setKeyboardMouseInputAllowed(bool allowed); - void toggleGamepadInputAllowed(); - void toggleKeyboardInputAllowed(); - void toggleMouseInputAllowed(); - void toggleKeyboardMouseInputAllowed(); - void toggleControlPanelVisibility(); - void notifyInputPermissionState(); - - float getAudioVolumeScalar() const - { - return m_AudioVolumeScalar.load(std::memory_order_relaxed); - } - - void setAudioVolumeScalar(float scalar); - void adjustAudioVolume(float delta); - void toggleAudioMute(); - void notifyAudioVolumeState(); - signals: void stageStarting(QString stage); @@ -264,9 +222,6 @@ private: static void clSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlags, uint8_t typeLeft, uint8_t typeRight, uint8_t *left, uint8_t *right); - static - void clSetInputPolicy(uint8_t allowKeyboard, uint8_t allowMouse, uint8_t allowGamepad, uint8_t reason); - static int arInit(int audioConfiguration, const POPUS_MULTISTREAM_CONFIGURATION opusConfig, @@ -287,15 +242,6 @@ private: static int drSubmitDecodeUnit(PDECODE_UNIT du); - static - Uint32 statusOverlayTimeoutCallback(Uint32 interval, void* param); - - void refreshControlPanelOverlay(); - void showTemporaryStatusOverlay(const char* text, Uint32 timeoutMs = 1500); - void applyHostInputPolicy(bool allowKeyboard, bool allowMouse, bool allowGamepad, uint8_t reason); - void sendInputPermissionStateToHost(uint8_t reason); - void updateEffectiveAudioMuteState(); - StreamingPreferences* m_Preferences; bool m_IsFullScreen; SupportedVideoFormatList m_SupportedVideoFormats; // Sorted in order of descending priority @@ -308,15 +254,7 @@ private: IVideoDecoder* m_VideoDecoder; SDL_mutex* m_DecoderLock; bool m_AudioDisabled; - std::atomic m_AudioMuted; - std::atomic m_ManualAudioMuted; - std::atomic m_AudioVolumeScalar; - std::atomic m_AllowGamepadInput; - std::atomic m_AllowKeyboardInput; - std::atomic m_AllowMouseInput; - std::atomic m_ControlPanelVisible; - std::atomic m_ConnectionStatus; - std::atomic m_StatusOverlayGeneration; + bool m_AudioMuted; Uint32 m_FullScreenFlag; QQuickWindow* m_QtWindow; bool m_UnexpectedTermination; @@ -340,7 +278,6 @@ private: OPUS_MULTISTREAM_CONFIGURATION m_OriginalAudioConfig; int m_AudioSampleCount; Uint32 m_DropAudioEndTime; - char m_TemporaryStatusOverlayText[160]; Overlay::OverlayManager m_OverlayManager; diff --git a/app/streaming/video/overlaymanager.cpp b/app/streaming/video/overlaymanager.cpp index 77150cc9..17e5e5c5 100644 --- a/app/streaming/video/overlaymanager.cpp +++ b/app/streaming/video/overlaymanager.cpp @@ -12,8 +12,8 @@ OverlayManager::OverlayManager() : m_Overlays[OverlayType::OverlayDebug].color = {0xD0, 0xD0, 0x00, 0xFF}; m_Overlays[OverlayType::OverlayDebug].fontSize = 20; - m_Overlays[OverlayType::OverlayStatusUpdate].color = {0xF0, 0xF0, 0xF0, 0xFF}; - m_Overlays[OverlayType::OverlayStatusUpdate].fontSize = 24; + m_Overlays[OverlayType::OverlayStatusUpdate].color = {0xCC, 0x00, 0x00, 0xFF}; + m_Overlays[OverlayType::OverlayStatusUpdate].fontSize = 36; // While TTF will usually not be initialized here, it is valid for that not to // be the case, since Session destruction is deferred and could overlap with @@ -146,45 +146,16 @@ void OverlayManager::notifyOverlayUpdated(OverlayType type) } } - SDL_Surface* newSurface = nullptr; - if (m_Overlays[type].enabled) { - // The _Wrapped variant is required for line breaks to work - SDL_Surface* textSurface = TTF_RenderText_Blended_Wrapped(m_Overlays[type].font, - m_Overlays[type].text, - m_Overlays[type].color, - 1024); - if (textSurface != nullptr && type == OverlayStatusUpdate) { - constexpr int kHorizontalPadding = 18; - constexpr int kVerticalPadding = 12; - - SDL_Surface* panelSurface = SDL_CreateRGBSurfaceWithFormat(0, - textSurface->w + (kHorizontalPadding * 2), - textSurface->h + (kVerticalPadding * 2), - 32, - SDL_PIXELFORMAT_ARGB8888); - if (panelSurface != nullptr) { - SDL_FillRect(panelSurface, - nullptr, - SDL_MapRGBA(panelSurface->format, 0x00, 0x00, 0x00, 0xA0)); - - SDL_Rect destination = {kHorizontalPadding, kVerticalPadding, textSurface->w, textSurface->h}; - SDL_SetSurfaceBlendMode(textSurface, SDL_BLENDMODE_BLEND); - SDL_BlitSurface(textSurface, nullptr, panelSurface, &destination); - SDL_FreeSurface(textSurface); - newSurface = panelSurface; - } - else { - newSurface = textSurface; - } - } - else { - newSurface = textSurface; - } - } - // Exchange the old surface with the new one - SDL_Surface* oldSurface = (SDL_Surface*)SDL_AtomicSetPtr((void**)&m_Overlays[type].surface, - newSurface); + SDL_Surface* oldSurface = (SDL_Surface*)SDL_AtomicSetPtr( + (void**)&m_Overlays[type].surface, + m_Overlays[type].enabled ? + // The _Wrapped variant is required for line breaks to work + TTF_RenderText_Blended_Wrapped(m_Overlays[type].font, + m_Overlays[type].text, + m_Overlays[type].color, + 1024) + : nullptr); // Notify the renderer m_Renderer->notifyOverlayUpdated(type); diff --git a/moonlight-common-c/moonlight-common-c b/moonlight-common-c/moonlight-common-c index 611a2e7f..6250fa29 160000 --- a/moonlight-common-c/moonlight-common-c +++ b/moonlight-common-c/moonlight-common-c @@ -1 +1 @@ -Subproject commit 611a2e7f8f6583d6d6aad30f0c8a02d6c07ab085 +Subproject commit 6250fa29ee87873716045e3b64f1f229374324e8 diff --git a/scripts/bootstrap-toolbox-build.sh b/scripts/bootstrap-toolbox-build.sh deleted file mode 100755 index d3f546c9..00000000 --- a/scripts/bootstrap-toolbox-build.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -JOBS="${JOBS:-$(nproc)}" -SKIP_BUILD=0 - -for arg in "$@"; do - case "$arg" in - --skip-build) - SKIP_BUILD=1 - ;; - --jobs=*) - JOBS="${arg#*=}" - ;; - *) - echo "Unknown argument: $arg" - echo "Usage: $0 [--skip-build] [--jobs=N]" - exit 1 - ;; - esac -done - -if [[ ! -f /run/.containerenv ]]; then - echo "Run this script inside your toolbox container." - exit 1 -fi - -if ! command -v dnf >/dev/null 2>&1; then - echo "This script expects a Fedora/RHEL-like toolbox with dnf." - exit 1 -fi - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -cd "$REPO_ROOT" - -FEDORA_VER="$(rpm -E %fedora)" - -if ! rpm -q rpmfusion-free-release >/dev/null 2>&1; then - sudo dnf -y install "https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-${FEDORA_VER}.noarch.rpm" -fi - -if ! rpm -q rpmfusion-nonfree-release >/dev/null 2>&1; then - sudo dnf -y install "https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-${FEDORA_VER}.noarch.rpm" -fi - -sudo dnf -y install \ - ffmpeg ffmpeg-devel \ - git make gcc gcc-c++ pkgconf-pkg-config \ - qt6-qtbase-devel qt6-qtdeclarative-devel qt6-qtquickcontrols2-devel qt6-qtsvg-devel qt6-qtwayland-devel \ - SDL2-devel SDL2_ttf-devel \ - opus-devel openssl-devel \ - libva-utils libva-devel libdrm-devel mesa-libEGL-devel mesa-libGL-devel \ - libX11-devel libXext-devel libXrandr-devel libXfixes-devel libXi-devel libXcursor-devel - -if rpm -q libva-intel-media-driver >/dev/null 2>&1; then - sudo dnf -y swap libva-intel-media-driver intel-media-driver --allowerasing -elif ! rpm -q intel-media-driver >/dev/null 2>&1; then - sudo dnf -y install intel-media-driver -fi - -git submodule update --init --recursive - -if command -v vainfo >/dev/null 2>&1; then - if ! vainfo 2>/dev/null | grep -q 'VAProfileHEVCMain'; then - echo "Warning: HEVC decode profile not detected in VAAPI." - fi - if ! vainfo 2>/dev/null | grep -q 'VAProfileH264High'; then - echo "Warning: H264 decode profile not detected in VAAPI." - fi -fi - -rm -rf Makefile */Makefile */Makefile.* app/release app/debug -qmake6 moonlight-qt.pro - -if [[ "$SKIP_BUILD" -eq 0 ]]; then - make release -j"$JOBS" -fi - -echo "Done."