diff --git a/app/gui/StreamSegue.qml b/app/gui/StreamSegue.qml index b3b0fd42..52cd9887 100644 --- a/app/gui/StreamSegue.qml +++ b/app/gui/StreamSegue.qml @@ -76,10 +76,8 @@ Item { streamSegueErrorDialog.text += "\n\n" + qsTr("This PC's Internet connection is blocking Moonlight. Streaming over the Internet may not work while connected to this network.") } - if (window.gamepadInputActive) { - // Re-enable GUI gamepad usage now - SdlGamepadKeyNavigation.enable() - } + // Re-enable GUI gamepad usage now + SdlGamepadKeyNavigation.enable() if (quitAfter) { if (streamSegueErrorDialog.text) { @@ -121,10 +119,8 @@ Item { // Show the toolbar again when popped off the stack toolBar.visible = true - if (window.gamepadInputActive) { - // Re-enable GUI gamepad usage now - SdlGamepadKeyNavigation.enable() - } + // Re-enable GUI gamepad usage now + SdlGamepadKeyNavigation.enable() } StackView.onActivated: { diff --git a/app/gui/main.qml b/app/gui/main.qml index 51d4b2db..bab9ecea 100644 --- a/app/gui/main.qml +++ b/app/gui/main.qml @@ -12,7 +12,6 @@ import SdlGamepadKeyNavigation 1.0 ApplicationWindow { property bool pollingActive: false - property bool gamepadInputActive: false // Set by SettingsView to force the back operation to pop all // pages except the initial view. This is required when doing @@ -33,7 +32,6 @@ ApplicationWindow { } SdlGamepadKeyNavigation.enable() - gamepadInputActive = true } Component.onCompleted: { @@ -160,11 +158,6 @@ ApplicationWindow { ComputerManager.stopPollingAsync() pollingActive = false } - - if (gamepadInputActive) { - SdlGamepadKeyNavigation.disable() - gamepadInputActive = false - } } else if (active) { // When we become visible and active again, start polling @@ -175,11 +168,10 @@ ApplicationWindow { ComputerManager.startPolling() pollingActive = true } - if (!gamepadInputActive) { - SdlGamepadKeyNavigation.enable() - gamepadInputActive = true - } } + + // Poll for gamepad input only when the window is in focus + SdlGamepadKeyNavigation.notifyWindowFocus(visible && active) } onActiveChanged: { @@ -192,23 +184,15 @@ ApplicationWindow { ComputerManager.startPolling() pollingActive = true } - if (!gamepadInputActive) { - SdlGamepadKeyNavigation.enable() - gamepadInputActive = true - } } else { // Start the inactivity timer to stop polling // if focus does not return within a few minutes. inactivityTimer.restart() - - // Immediately stop gamepad input since we aren't - // the active window anymore. - if (gamepadInputActive) { - SdlGamepadKeyNavigation.disable() - gamepadInputActive = false - } } + + // Poll for gamepad input only when the window is in focus + SdlGamepadKeyNavigation.notifyWindowFocus(visible && active) } // Workaround for lack of instanceof in Qt 5.9. diff --git a/app/gui/sdlgamepadkeynavigation.cpp b/app/gui/sdlgamepadkeynavigation.cpp index e51eb776..c10ae4dd 100644 --- a/app/gui/sdlgamepadkeynavigation.cpp +++ b/app/gui/sdlgamepadkeynavigation.cpp @@ -13,6 +13,7 @@ SdlGamepadKeyNavigation::SdlGamepadKeyNavigation(StreamingPreferences* prefs) m_Enabled(false), m_UiNavMode(false), m_FirstPoll(false), + m_HasFocus(false), m_LastAxisNavigationEventTime(0) { m_PollingTimer = new QTimer(this); @@ -63,13 +64,10 @@ void SdlGamepadKeyNavigation::enable() } } - // Flush events on the first poll - m_FirstPoll = true; - - // Poll every 50 ms for a new joystick event - m_PollingTimer->start(50); - m_Enabled = true; + + // Start the polling timer if the window is focused + updateTimerState(); } void SdlGamepadKeyNavigation::disable() @@ -78,7 +76,9 @@ void SdlGamepadKeyNavigation::disable() return; } - m_PollingTimer->stop(); + m_Enabled = false; + updateTimerState(); + Q_ASSERT(!m_PollingTimer->isActive()); while (!m_Gamepads.isEmpty()) { SDL_GameControllerClose(m_Gamepads[0]); @@ -86,8 +86,12 @@ void SdlGamepadKeyNavigation::disable() } SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); +} - m_Enabled = false; +void SdlGamepadKeyNavigation::notifyWindowFocus(bool hasFocus) +{ + m_HasFocus = hasFocus; + updateTimerState(); } void SdlGamepadKeyNavigation::onPollingTimerFired() @@ -261,6 +265,20 @@ void SdlGamepadKeyNavigation::sendKey(QEvent::Type type, Qt::Key key, Qt::Keyboa } } +void SdlGamepadKeyNavigation::updateTimerState() +{ + if (m_PollingTimer->isActive() && (!m_HasFocus || !m_Enabled)) { + m_PollingTimer->stop(); + } + else if (!m_PollingTimer->isActive() && m_HasFocus && m_Enabled) { + // Flush events on the first poll + m_FirstPoll = true; + + // Poll every 50 ms for a new joystick event + m_PollingTimer->start(50); + } +} + void SdlGamepadKeyNavigation::setUiNavMode(bool uiNavMode) { m_UiNavMode = uiNavMode; diff --git a/app/gui/sdlgamepadkeynavigation.h b/app/gui/sdlgamepadkeynavigation.h index af283be1..7c26526a 100644 --- a/app/gui/sdlgamepadkeynavigation.h +++ b/app/gui/sdlgamepadkeynavigation.h @@ -20,6 +20,8 @@ public: Q_INVOKABLE void disable(); + Q_INVOKABLE void notifyWindowFocus(bool hasFocus); + Q_INVOKABLE void setUiNavMode(bool settingsMode); Q_INVOKABLE int getConnectedGamepads(); @@ -27,6 +29,8 @@ public: private: void sendKey(QEvent::Type type, Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + void updateTimerState(); + private slots: void onPollingTimerFired(); @@ -37,5 +41,6 @@ private: bool m_Enabled; bool m_UiNavMode; bool m_FirstPoll; + bool m_HasFocus; Uint32 m_LastAxisNavigationEventTime; };