diff options
| author | Tobias Zimmermann <cu3po42@gmail.com> | 2024-03-03 01:17:02 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-03 00:17:02 +0000 |
| commit | 964f1a438df5114fd9d771f24015e95b8061e503 (patch) | |
| tree | da67dfeecbdb4ee04296b45278fcc725f43166bf /src | |
| parent | 508262b7db6e8e88573a4069c88b4fb88ccff1d5 (diff) | |
keybinds: Add the 'catchall' keyword that matches all keys (#4930)
* Add the 'catchall' keyword that matches all keys
This keyword can be used to define arbitrary keybinds. The only special
behavior that it exhibits is that it matches every key, including
modifier keys. Any flags still apply normally.
This commit also fixes an issue that keys bound via the code:KEYCODE
format were not unbound correctly.
* Disallow catchall keybinds outside of submaps
A catchall keybind outside a submap would prevent essentially all key
events from going through to applications and would be difficult to
remove again.
Diffstat (limited to 'src')
| -rw-r--r-- | src/config/ConfigManager.cpp | 30 | ||||
| -rw-r--r-- | src/debug/HyprCtl.cpp | 8 | ||||
| -rw-r--r-- | src/managers/KeybindManager.cpp | 16 | ||||
| -rw-r--r-- | src/managers/KeybindManager.hpp | 9 |
4 files changed, 39 insertions, 24 deletions
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 4ae62392..59de33bb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1732,6 +1732,17 @@ std::optional<std::string> CConfigManager::handleAnimation(const std::string& co return {}; } +SParsedKey parseKey(const std::string& key) { + if (isNumber(key) && std::stoi(key) > 9) + return {.keycode = std::stoi(key)}; + else if (key.starts_with("code:") && isNumber(key.substr(5))) + return {.keycode = std::stoi(key.substr(5))}; + else if (key == "catchall") + return {.catchAll = true}; + else + return {.key = key}; +} + std::optional<std::string> CConfigManager::handleBind(const std::string& command, const std::string& value) { // example: // bind[fl]=SUPER,G,exec,dmenu_run <args> @@ -1807,14 +1818,15 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command } if (KEY != "") { - if (isNumber(KEY) && std::stoi(KEY) > 9) - g_pKeybindManager->addKeybind( - SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); - else if (KEY.starts_with("code:") && isNumber(KEY.substr(5))) - g_pKeybindManager->addKeybind( - SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); - else - g_pKeybindManager->addKeybind(SKeybind{KEY, 0, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); + SParsedKey parsedKey = parseKey(KEY); + + if (parsedKey.catchAll && m_szCurrentSubmap == "") { + Debug::log(ERR, "Catchall not allowed outside of submap!"); + return "Invalid catchall, catchall keybinds are only allowed in submaps."; + } + + g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, parsedKey.keycode, parsedKey.catchAll, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, + nonConsuming, transparent, ignoreMods}); } return {}; @@ -1825,7 +1837,7 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]); - const auto KEY = ARGS[1]; + const auto KEY = parseKey(ARGS[1]); g_pKeybindManager->removeKeybind(MOD, KEY); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 962496f7..a65533d2 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -718,8 +718,8 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { if (kb.nonConsuming) ret += "n"; - ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, kb.key, kb.keycode, kb.handler, - kb.arg); + ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, kb.key, + kb.keycode, kb.catchAll, kb.handler, kb.arg); } } else { // json @@ -737,11 +737,13 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "submap": "{}", "key": "{}", "keycode": {}, + "catch_all": {}, "dispatcher": "{}", "arg": "{}" }},)#", kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false", - kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); + kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false", escapeJSONStrings(kb.handler), + escapeJSONStrings(kb.arg)); } trimTrailingComma(ret); ret += "]"; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 1ab8fa91..28c72029 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -95,18 +95,9 @@ void CKeybindManager::addKeybind(SKeybind kb) { m_pActiveKeybind = nullptr; } -void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) { +void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) { - if (isNumber(key) && std::stoi(key) > 9) { - const uint32_t KEYNUM = std::stoi(key); - - if (it->modmask == mod && it->keycode == KEYNUM) { - it = m_lKeybinds.erase(it); - - if (it == m_lKeybinds.end()) - break; - } - } else if (it->modmask == mod && it->key == key) { + if (it->modmask == mod && it->key == key.key && it->keycode == key.keycode && it->catchAll == key.catchAll) { it = m_lKeybinds.erase(it); if (it == m_lKeybinds.end()) @@ -527,6 +518,9 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi } else if (k.keycode != 0) { if (key.keycode != k.keycode) continue; + } else if (k.catchAll) { + if (found) + continue; } else { // oMg such performance hit!!11! // this little maneouver is gonna cost us 4µs diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index edd9ede2..561ee1ab 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -13,6 +13,7 @@ class CPluginSystem; struct SKeybind { std::string key = ""; uint32_t keycode = 0; + bool catchAll = false; uint32_t modmask = 0; std::string handler = ""; std::string arg = ""; @@ -44,6 +45,12 @@ struct SPressedKeyWithMods { bool sent = false; }; +struct SParsedKey { + std::string key = ""; + uint32_t keycode = 0; + bool catchAll = false; +}; + class CKeybindManager { public: CKeybindManager(); @@ -57,7 +64,7 @@ class CKeybindManager { void onSwitchOffEvent(const std::string&); void addKeybind(SKeybind); - void removeKeybind(uint32_t, const std::string&); + void removeKeybind(uint32_t, const SParsedKey&); uint32_t stringToModMask(std::string); uint32_t keycodeToModifier(xkb_keycode_t); void clearKeybinds(); |
