From dcb909df0466a8b9fe07ea7c420b840e2e910223 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sun, 10 Sep 2023 16:27:14 +0100 Subject: [PATCH] keybinds: track pressed special binds Ignore mods only if we're processing a special bind, and only if it's pressed. Otherwise we might shadow normal key releases via ignoring mods. Fixes #3240 --- src/managers/KeybindManager.cpp | 15 ++++++++++++++- src/managers/KeybindManager.hpp | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cf0c573fc..98439695a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -71,6 +71,12 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["global"] = global; m_tScrollTimer.reset(); + + g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, std::any param) { + // clear cuz realloc'd + m_pActiveKeybind = nullptr; + m_vPressedSpecialBinds.clear(); + }); } void CKeybindManager::addKeybind(SKeybind kb) { @@ -422,7 +428,9 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& for (auto& k : m_lKeybinds) { const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "mouse"; - const bool IGNOREMODS = SPECIALDISPATCHER && !pressed; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. + const bool SPECIALTRIGGERED = + std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == &k; }) != m_vPressedSpecialBinds.end(); + const bool IGNOREMODS = SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. if ((modmask != k.modmask && !IGNOREMODS) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed) continue; @@ -464,6 +472,11 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler); + if (SPECIALTRIGGERED && !pressed) + std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == &k; }); + else if (SPECIALDISPATCHER && pressed) + m_vPressedSpecialBinds.push_back(&k); + // Should never happen, as we check in the ConfigManager, but oh well if (DISPATCHER == m_mDispatchers.end()) { Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 5151710e5..af938c429 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -75,6 +75,7 @@ class CKeybindManager { uint32_t m_uLastMouseCode = 0; bool m_bIsMouseBindActive = false; + std::vector m_vPressedSpecialBinds; int m_iPassPressed = -1; // used for pass