mirror of https://github.com/PCSX2/pcsx2.git
Qt: Clear all keyboard bind states when focus is lost
This commit is contained in:
parent
262b5f1dc0
commit
520320535e
|
@ -795,17 +795,22 @@ void EmuThread::onDisplayWindowResized(int width, int height, float scale)
|
||||||
void EmuThread::onApplicationStateChanged(Qt::ApplicationState state)
|
void EmuThread::onApplicationStateChanged(Qt::ApplicationState state)
|
||||||
{
|
{
|
||||||
// NOTE: This is executed on the emu thread, not UI thread.
|
// NOTE: This is executed on the emu thread, not UI thread.
|
||||||
if (!m_pause_on_focus_loss || !VMManager::HasValidVM())
|
if (!VMManager::HasValidVM())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const bool focus_loss = (state != Qt::ApplicationActive);
|
const bool focus_loss = (state != Qt::ApplicationActive);
|
||||||
if (focus_loss)
|
if (focus_loss)
|
||||||
{
|
{
|
||||||
if (!m_was_paused_by_focus_loss && VMManager::GetState() == VMState::Running)
|
if (m_pause_on_focus_loss && !m_was_paused_by_focus_loss && VMManager::GetState() == VMState::Running)
|
||||||
{
|
{
|
||||||
m_was_paused_by_focus_loss = true;
|
m_was_paused_by_focus_loss = true;
|
||||||
VMManager::SetPaused(true);
|
VMManager::SetPaused(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the state of all keyboard binds.
|
||||||
|
// That way, if we had a key held down, and lost focus, the bind won't be stuck enabled because we never
|
||||||
|
// got the key release message, because it happened in another window which "stole" the event.
|
||||||
|
InputManager::ClearBindStateFromSource(InputManager::MakeHostKeyboardKey(0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -923,6 +923,71 @@ bool InputManager::ProcessEvent(InputBindingKey key, float value, bool skip_butt
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputManager::ClearBindStateFromSource(InputBindingKey key)
|
||||||
|
{
|
||||||
|
// 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_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))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < binding->num_keys; i++)
|
||||||
|
{
|
||||||
|
if (binding->keys[i].MaskDirection() != match_key)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::get<InputAxisEventHandler>(binding->handler)(0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now go through the button handlers, and pick them off.
|
||||||
|
bool matched;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
matched = false;
|
||||||
|
|
||||||
|
for (const auto& [match_key, binding] : s_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))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < binding->num_keys; i++)
|
||||||
|
{
|
||||||
|
if (binding->keys[i].MaskDirection() != match_key)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Skip if we weren't pressed.
|
||||||
|
const u8 bit = static_cast<u8>(1) << i;
|
||||||
|
if ((binding->current_mask & bit) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Only fire handler if we're changing from active state.
|
||||||
|
const u8 current_mask = binding->current_mask;
|
||||||
|
binding->current_mask &= ~bit;
|
||||||
|
|
||||||
|
if (current_mask == binding->full_mask)
|
||||||
|
{
|
||||||
|
std::get<InputButtonEventHandler>(binding->handler)(0.0f);
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to start again, might've reloaded.
|
||||||
|
if (matched)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (matched);
|
||||||
|
}
|
||||||
|
|
||||||
bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInputBinding generic_key)
|
bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInputBinding generic_key)
|
||||||
{
|
{
|
||||||
// does imgui want the event?
|
// does imgui want the event?
|
||||||
|
|
|
@ -257,6 +257,9 @@ namespace InputManager
|
||||||
/// Returns true if anything was bound to this key, otherwise false.
|
/// Returns true if anything was bound to this key, otherwise false.
|
||||||
bool InvokeEvents(InputBindingKey key, float value, GenericInputBinding generic_key = GenericInputBinding::Unknown);
|
bool InvokeEvents(InputBindingKey key, float value, GenericInputBinding generic_key = GenericInputBinding::Unknown);
|
||||||
|
|
||||||
|
/// Clears internal state for any binds with a matching source/index.
|
||||||
|
void ClearBindStateFromSource(InputBindingKey key);
|
||||||
|
|
||||||
/// Sets a hook which can be used to intercept events before they're processed by the normal bindings.
|
/// Sets a hook which can be used to intercept events before they're processed by the normal bindings.
|
||||||
/// This is typically used when binding new controls to detect what gets pressed.
|
/// This is typically used when binding new controls to detect what gets pressed.
|
||||||
void SetHook(InputInterceptHook::Callback callback);
|
void SetHook(InputInterceptHook::Callback callback);
|
||||||
|
|
Loading…
Reference in New Issue