From 6113f4da7fa9839645525e57ff841db5bb00e475 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:48:13 +0000 Subject: [PATCH] keybinds: allow repeating multiple binds (#8290) --- src/managers/KeybindManager.cpp | 69 +++++++++++++++------------------ src/managers/KeybindManager.hpp | 7 ++-- 2 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4d2f4dcc..a0cd01a9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -144,11 +144,30 @@ CKeybindManager::CKeybindManager() { }, nullptr); + m_pRepeatKeyTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired()) + return; + + for (SKeybind* k : m_vActiveKeybinds) { + const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler); + + Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); + DISPATCHER->second(k->arg); + } + + const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); + self->updateTimeout(std::chrono::milliseconds(1000 / PACTIVEKEEB->repeatRate)); + }, + nullptr); + g_pEventLoopManager->addTimer(m_pLongPressTimer); + g_pEventLoopManager->addTimer(m_pRepeatKeyTimer); static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; m_vPressedSpecialBinds.clear(); }); @@ -161,12 +180,16 @@ CKeybindManager::~CKeybindManager() { g_pEventLoopManager->removeTimer(m_pLongPressTimer); m_pLongPressTimer.reset(); } + if (m_pRepeatKeyTimer && g_pEventLoopManager) { + g_pEventLoopManager->removeTimer(m_pRepeatKeyTimer); + m_pRepeatKeyTimer.reset(); + } } void CKeybindManager::addKeybind(SKeybind kb) { m_lKeybinds.push_back(kb); - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; } @@ -180,7 +203,7 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { } } - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; } @@ -426,11 +449,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { .submapAtPress = m_szCurrentSelectedSubmap, }; - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; @@ -482,11 +501,7 @@ bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) { m_tScrollTimer.reset(); - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); bool found = false; if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { @@ -525,11 +540,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { .modmaskAtPressTime = MODS, }; - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) { m_dPressedKeys.push_back(KEY); @@ -580,22 +591,6 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true); } -int repeatKeyHandler(void* data) { - SKeybind** ppActiveKeybind = (SKeybind**)data; - - if (!*ppActiveKeybind || g_pSeatManager->keyboard.expired()) - return 0; - - const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler); - - Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); - DISPATCHER->second((*ppActiveKeybind)->arg); - - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate); - - return 0; -} - eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set keybindKeysyms, const std::set pressedKeysyms) { // Returns whether two sets of keysyms are equal, partially equal, or not // matching. (Partially matching means that pressed is a subset of bound) @@ -770,12 +765,10 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } if (k.repeat) { - m_pActiveKeybind = &k; - m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind); - const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); - wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay); + m_vActiveKeybinds.push_back(&k); + m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); } if (!k.nonConsuming) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 4a0af6e9..d375db0f 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -102,8 +102,6 @@ class CKeybindManager { std::unordered_map> m_mDispatchers; - wl_event_source* m_pActiveKeybindEventSource = nullptr; - bool m_bGroupsLocked = false; std::list m_lKeybinds; @@ -121,8 +119,9 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - SKeybind * m_pActiveKeybind = nullptr, *m_pLastLongPressKeybind = nullptr; - SP m_pLongPressTimer; + std::vector m_vActiveKeybinds; + SKeybind* m_pLastLongPressKeybind = nullptr; + SP m_pLongPressTimer, m_pRepeatKeyTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0;