Rework window focus tracking for gamepad navigation

This commit is contained in:
Cameron Gutman 2024-10-18 21:20:56 -05:00
parent 4af9623727
commit b6a3369243
4 changed files with 41 additions and 38 deletions

View File

@ -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()
}
if (quitAfter) {
if (streamSegueErrorDialog.text) {
@ -121,11 +119,9 @@ Item {
// Show the toolbar again when popped off the stack
toolBar.visible = true
if (window.gamepadInputActive) {
// Re-enable GUI gamepad usage now
SdlGamepadKeyNavigation.enable()
}
}
StackView.onActivated: {
// Hide the toolbar before we start loading

View File

@ -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.

View File

@ -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;

View File

@ -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;
};