diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 52afbfdd6..74cecc454 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -85,28 +85,35 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t* keysyms; - int syms = xkb_state_key_get_syms(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE, &keysyms); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE); const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + bool found = false; if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { - for (int i = 0; i < syms; ++i) - found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i], 0, true) || found; + m_dPressedKeycodes.push_back(KEYCODE); + m_dPressedKeysyms.push_back(keysym); - found = g_pKeybindManager->handleKeybinds(MODS, 0, KEYCODE, true) || found; + found = g_pKeybindManager->handleKeybinds(MODS, keysym, 0, true, e->time_msec) || found; + + found = g_pKeybindManager->handleKeybinds(MODS, 0, KEYCODE, true, e->time_msec) || found; } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) { - for (int i = 0; i < syms; ++i) - found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i], 0, false) || found; - found = g_pKeybindManager->handleKeybinds(MODS, 0, KEYCODE, false) || found; + m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE)); + m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym)); + + found = g_pKeybindManager->handleKeybinds(MODS, keysym, 0, false, e->time_msec) || found; + + found = g_pKeybindManager->handleKeybinds(MODS, 0, KEYCODE, false, e->time_msec) || found; + + shadowKeybinds(); } return !found; } -bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key, const int& keycode, bool pressed) { +bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key, const int& keycode, bool pressed, uint32_t time) { bool found = false; if (handleInternalKeybinds(key)) @@ -115,8 +122,14 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t if (g_pCompositor->m_sSeat.exclusiveClient) Debug::log(LOG, "Keybind handling only locked (inhibitor)"); + if (pressed && m_kHeldBack) { + // release the held back event + wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, time, m_kHeldBack, WL_KEYBOARD_KEY_STATE_PRESSED); + m_kHeldBack = 0; + } + for (auto& k : m_lKeybinds) { - if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release)) + if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release) || k.shadowed) continue; if (k.keycode != -1) { @@ -139,6 +152,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t if (pressed && k.release) { // suppress down event + m_kHeldBack = key; return true; } @@ -153,12 +167,40 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t DISPATCHER->second(k.arg); } + shadowKeybinds(); + found = true; } return found; } +void CKeybindManager::shadowKeybinds() { + // shadow disables keybinds after one has been triggered + + for (auto& k : m_lKeybinds) { + + bool shadow = false; + + const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); + + for (auto& pk : m_dPressedKeysyms) { + if ((pk == KBKEY || pk == KBKEYUPPER)) { + shadow = true; + } + } + + for (auto& pk : m_dPressedKeycodes) { + if (pk == (unsigned int)k.keycode) { + shadow = true; + } + } + + k.shadowed = shadow; + } +} + bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // Handles the CTRL+ALT+FX TTY keybinds if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12)) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index fc3b06f82..62568fc0d 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -15,6 +15,9 @@ struct SKeybind { bool locked = false; std::string submap = ""; bool release = false; + + // DO NOT INITIALIZE + bool shadowed = false; }; class CKeybindManager { @@ -32,10 +35,16 @@ public: private: std::list m_lKeybinds; + std::deque m_dPressedKeysyms; + std::deque m_dPressedKeycodes; inline static std::string m_szCurrentSelectedSubmap = ""; - bool handleKeybinds(const uint32_t&, const xkb_keysym_t&, const int&, bool); + xkb_keysym_t m_kHeldBack = 0; + + bool handleKeybinds(const uint32_t&, const xkb_keysym_t&, const int&, bool, uint32_t); + + void shadowKeybinds(); bool handleInternalKeybinds(xkb_keysym_t); bool handleVT(xkb_keysym_t);