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
This commit is contained in:
vaxerski 2023-09-10 16:27:14 +01:00
parent 807fc20525
commit dcb909df04
2 changed files with 15 additions and 1 deletions

View file

@ -71,6 +71,12 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["global"] = global; m_mDispatchers["global"] = global;
m_tScrollTimer.reset(); 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) { void CKeybindManager::addKeybind(SKeybind kb) {
@ -422,7 +428,9 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
for (auto& k : m_lKeybinds) { for (auto& k : m_lKeybinds) {
const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "mouse"; 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) if ((modmask != k.modmask && !IGNOREMODS) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)
continue; 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); 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 // Should never happen, as we check in the ConfigManager, but oh well
if (DISPATCHER == m_mDispatchers.end()) { if (DISPATCHER == m_mDispatchers.end()) {
Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler); Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler);

View file

@ -75,6 +75,7 @@ class CKeybindManager {
uint32_t m_uLastMouseCode = 0; uint32_t m_uLastMouseCode = 0;
bool m_bIsMouseBindActive = false; bool m_bIsMouseBindActive = false;
std::vector<SKeybind*> m_vPressedSpecialBinds;
int m_iPassPressed = -1; // used for pass int m_iPassPressed = -1; // used for pass