Fix controller input lingering when unfocused (#210)

This commit is contained in:
Hyper 2025-01-26 20:49:13 +00:00 committed by GitHub
parent 4d41d8eaae
commit a5db997e5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 89 additions and 76 deletions

View file

@ -68,7 +68,7 @@ public:
bool CanPoll() bool CanPoll()
{ {
return controller && (GameWindow::s_isFocused || Config::AllowBackgroundInput); return controller;
} }
void PollAxis() void PollAxis()

View file

@ -1,4 +1,6 @@
#include "hid.h" #include "hid.h"
#include <ui/game_window.h>
#include <user/config.h>
hid::EInputDevice hid::g_inputDevice; hid::EInputDevice hid::g_inputDevice;
hid::EInputDevice hid::g_inputDeviceController; hid::EInputDevice hid::g_inputDeviceController;
@ -11,6 +13,11 @@ void hid::SetProhibitedButtons(uint16_t wButtons)
hid::g_prohibitedButtons = wButtons; hid::g_prohibitedButtons = wButtons;
} }
bool hid::IsInputAllowed()
{
return GameWindow::s_isFocused || Config::AllowBackgroundInput;
}
bool hid::IsInputDeviceController() bool hid::IsInputDeviceController()
{ {
return hid::g_inputDevice != hid::EInputDevice::Keyboard && return hid::g_inputDevice != hid::EInputDevice::Keyboard &&

View file

@ -41,6 +41,7 @@ namespace hid
uint32_t SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration); uint32_t SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration);
uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps); uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps);
bool IsInputAllowed();
bool IsInputDeviceController(); bool IsInputDeviceController();
std::string GetInputDeviceName(); std::string GetInputDeviceName();
} }

View file

@ -405,7 +405,8 @@ uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_STATE* st
{ {
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
uint32_t result = hid::GetState(userIndex, state); if (hid::IsInputAllowed())
hid::GetState(userIndex, state);
if (GameWindow::s_isFocused) if (GameWindow::s_isFocused)
{ {

View file

@ -123,6 +123,9 @@ public:
void OnSDLEvent(SDL_Event* event) override void OnSDLEvent(SDL_Event* event) override
{ {
if (!hid::IsInputAllowed())
return;
switch (event->type) switch (event->type)
{ {
#ifdef UI_KBM_SUPPORT #ifdef UI_KBM_SUPPORT

View file

@ -159,100 +159,103 @@ class SDLEventListenerForInstaller : public SDLEventListener
public: public:
void OnSDLEvent(SDL_Event *event) override void OnSDLEvent(SDL_Event *event) override
{ {
if (!InstallerWizard::s_isVisible || !g_currentMessagePrompt.empty() || g_currentPickerVisible || !hid::IsInputAllowed())
return;
constexpr float AxisValueRange = 32767.0f; constexpr float AxisValueRange = 32767.0f;
constexpr float AxisTapRange = 0.5f; constexpr float AxisTapRange = 0.5f;
if (!InstallerWizard::s_isVisible || !g_currentMessagePrompt.empty() || g_currentPickerVisible)
{
return;
}
int newCursorIndex = -1; int newCursorIndex = -1;
ImVec2 tapDirection = {}; ImVec2 tapDirection = {};
switch (event->type) switch (event->type)
{ {
case SDL_KEYDOWN: case SDL_KEYDOWN:
switch (event->key.keysym.scancode)
{ {
case SDL_SCANCODE_LEFT: switch (event->key.keysym.scancode)
case SDL_SCANCODE_RIGHT:
tapDirection.x = (event->key.keysym.scancode == SDL_SCANCODE_RIGHT) ? 1.0f : -1.0f;
break;
case SDL_SCANCODE_UP:
case SDL_SCANCODE_DOWN:
tapDirection.y = (event->key.keysym.scancode == SDL_SCANCODE_DOWN) ? 1.0f : -1.0f;
break;
case SDL_SCANCODE_RETURN:
case SDL_SCANCODE_KP_ENTER:
g_currentCursorAccepted = (g_currentCursorIndex >= 0);
break;
}
break;
case SDL_CONTROLLERBUTTONDOWN:
switch (event->cbutton.button)
{
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
tapDirection = { -1.0f, 0.0f };
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
tapDirection = { 1.0f, 0.0f };
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
tapDirection = { 0.0f, -1.0f };
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
tapDirection = { 0.0f, 1.0f };
break;
case SDL_CONTROLLER_BUTTON_A:
g_currentCursorAccepted = (g_currentCursorIndex >= 0);
break;
}
break;
case SDL_CONTROLLERAXISMOTION:
{
if (event->caxis.axis < 2)
{
float newAxisValue = event->caxis.value / AxisValueRange;
bool sameDirection = (newAxisValue * g_joypadAxis[event->caxis.axis]) > 0.0f;
bool wasInRange = abs(g_joypadAxis[event->caxis.axis]) > AxisTapRange;
bool isInRange = abs(newAxisValue) > AxisTapRange;
if (sameDirection && !wasInRange && isInRange)
{ {
tapDirection[event->caxis.axis] = newAxisValue; case SDL_SCANCODE_LEFT:
case SDL_SCANCODE_RIGHT:
tapDirection.x = (event->key.keysym.scancode == SDL_SCANCODE_RIGHT) ? 1.0f : -1.0f;
break;
case SDL_SCANCODE_UP:
case SDL_SCANCODE_DOWN:
tapDirection.y = (event->key.keysym.scancode == SDL_SCANCODE_DOWN) ? 1.0f : -1.0f;
break;
case SDL_SCANCODE_RETURN:
case SDL_SCANCODE_KP_ENTER:
g_currentCursorAccepted = (g_currentCursorIndex >= 0);
break;
} }
g_joypadAxis[event->caxis.axis] = newAxisValue; break;
} }
break; case SDL_CONTROLLERBUTTONDOWN:
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEMOTION:
{
for (size_t i = 0; i < g_currentCursorRects.size(); i++)
{ {
auto &currentRect = g_currentCursorRects[i]; switch (event->cbutton.button)
if (ImGui::IsMouseHoveringRect(currentRect.first, currentRect.second, false))
{ {
newCursorIndex = int(i); case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
tapDirection = { -1.0f, 0.0f };
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
tapDirection = { 1.0f, 0.0f };
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
tapDirection = { 0.0f, -1.0f };
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
tapDirection = { 0.0f, 1.0f };
break;
case SDL_CONTROLLER_BUTTON_A:
g_currentCursorAccepted = (g_currentCursorIndex >= 0);
break;
}
if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT) break;
}
case SDL_CONTROLLERAXISMOTION:
{
if (event->caxis.axis < 2)
{
float newAxisValue = event->caxis.value / AxisValueRange;
bool sameDirection = (newAxisValue * g_joypadAxis[event->caxis.axis]) > 0.0f;
bool wasInRange = abs(g_joypadAxis[event->caxis.axis]) > AxisTapRange;
bool isInRange = abs(newAxisValue) > AxisTapRange;
if (sameDirection && !wasInRange && isInRange)
{ {
g_currentCursorAccepted = true; tapDirection[event->caxis.axis] = newAxisValue;
} }
break; g_joypadAxis[event->caxis.axis] = newAxisValue;
} }
break;
} }
if (newCursorIndex < 0) case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEMOTION:
{ {
g_currentCursorIndex = -1; for (size_t i = 0; i < g_currentCursorRects.size(); i++)
} {
auto &currentRect = g_currentCursorRects[i];
break; if (ImGui::IsMouseHoveringRect(currentRect.first, currentRect.second, false))
} {
newCursorIndex = int(i);
if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT)
g_currentCursorAccepted = true;
break;
}
}
if (newCursorIndex < 0)
g_currentCursorIndex = -1;
break;
}
} }
if (tapDirection.x != 0.0f || tapDirection.y != 0.0f) if (tapDirection.x != 0.0f || tapDirection.y != 0.0f)
@ -300,9 +303,7 @@ public:
if (newCursorIndex >= 0) if (newCursorIndex >= 0)
{ {
if (g_currentCursorIndex != newCursorIndex) if (g_currentCursorIndex != newCursorIndex)
{
Game_PlaySound("sys_worldmap_cursor"); Game_PlaySound("sys_worldmap_cursor");
}
g_currentCursorIndex = newCursorIndex; g_currentCursorIndex = newCursorIndex;
} }

View file

@ -53,7 +53,7 @@ class SDLEventListenerForMessageWindow : public SDLEventListener
public: public:
void OnSDLEvent(SDL_Event* event) override void OnSDLEvent(SDL_Event* event) override
{ {
if (App::s_isInit || !MessageWindow::s_isVisible) if (App::s_isInit || !MessageWindow::s_isVisible || !hid::IsInputAllowed())
return; return;
constexpr float axisValueRange = 32767.0f; constexpr float axisValueRange = 32767.0f;