diff --git a/src/util/input_manager.cpp b/src/util/input_manager.cpp index dbb46589e..85522cb14 100644 --- a/src/util/input_manager.cpp +++ b/src/util/input_manager.cpp @@ -169,6 +169,8 @@ static bool ShouldMaskBackgroundInput(InputBindingKey key); static bool DoEventHook(InputBindingKey key, float value); static bool PreprocessEvent(InputBindingKey key, float value, GenericInputBinding generic_key); static bool ProcessEvent(InputBindingKey key, float value, bool skip_button_handlers); +template +static void ClearBindState(Predicate&& matches); static void LoadMacroButtonConfig(const SettingsInterface& si, const std::string& section, u32 pad, const Controller::ControllerInfo& cinfo); @@ -1309,14 +1311,14 @@ bool InputManager::ProcessEvent(InputBindingKey key, float value, bool skip_butt return true; } -void InputManager::ClearBindStateFromSource(InputBindingKey key) +template +void InputManager::ClearBindState(Predicate&& matches) { // Why are we doing it this way? Because any of the bindings could cause a reload and invalidate our iterators :(. // Axis handlers should be fine, so we'll do those as a first pass. for (const auto& [match_key, binding] : s_state.binding_map) { - if (key.source_type != match_key.source_type || key.source_subtype != match_key.source_subtype || - key.source_index != match_key.source_index || !IsAxisHandler(binding->handler)) + if (!matches(match_key) || !IsAxisHandler(binding->handler)) { continue; } @@ -1339,8 +1341,7 @@ void InputManager::ClearBindStateFromSource(InputBindingKey key) for (const auto& [match_key, binding] : s_state.binding_map) { - if (key.source_type != match_key.source_type || key.source_subtype != match_key.source_subtype || - key.source_index != match_key.source_index || IsAxisHandler(binding->handler)) + if (!matches(match_key) || IsAxisHandler(binding->handler)) { continue; } @@ -1374,6 +1375,13 @@ void InputManager::ClearBindStateFromSource(InputBindingKey key) } while (matched); } +void InputManager::ClearBindStateFromSource(InputBindingKey key) +{ + ClearBindState([key](const InputBindingKey& match_key) { + return (key.source_type == match_key.source_type && key.source_index == match_key.source_index); + }); +} + void InputManager::SynchronizeBindingHandlerState() { // should be called on the main thread, so no need to lock @@ -1652,6 +1660,7 @@ void InputManager::UpdateInputIgnoreState() if (s_state.ignore_input_events) { VERBOSE_COLOR_LOG(StrongOrange, "Application in background, ignoring input events"); + ClearBindState([](const InputBindingKey& key) { return (key.source_type > InputSourceType::Pointer); }); } else { @@ -1938,6 +1947,7 @@ void InputManager::OnInputDeviceConnected(InputBindingKey key, std::string_view void InputManager::OnInputDeviceDisconnected(InputBindingKey key, std::string_view identifier) { INFO_LOG("Device '{}' disconnected", identifier); + ClearBindStateFromSource(key); Host::OnInputDeviceDisconnected(key, identifier); if (System::IsValid() || VideoThread::IsFullscreenUIRequested())