diff options
| author | Can <45462997+yungcxn@users.noreply.github.com> | 2024-05-24 20:58:26 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-24 20:58:26 +0200 |
| commit | ce17961aad6f9164e5d026d19efd42b07b123bff (patch) | |
| tree | 0bd5c9ea8da8a777734baa57fa301bdb5580511c /src/managers/KeybindManager.cpp | |
| parent | 6d67b84469d5c12c5bbc4880f327ca8eb7a2ed2d (diff) | |
keybinds: Added new dispatcher (sendshortcut) (#6174)
Diffstat (limited to 'src/managers/KeybindManager.cpp')
| -rw-r--r-- | src/managers/KeybindManager.cpp | 154 |
1 files changed, 153 insertions, 1 deletions
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index e23cb500..41b82d10 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -89,6 +89,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["focuswindow"] = focusWindow; m_mDispatchers["submap"] = setSubmap; m_mDispatchers["pass"] = pass; + m_mDispatchers["sendshortcut"] = sendshortcut; m_mDispatchers["layoutmsg"] = layoutmsg; m_mDispatchers["toggleopaque"] = toggleOpaque; m_mDispatchers["dpms"] = dpms; @@ -589,7 +590,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi } 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 == "sendshortcut" || k.handler == "mouse"; const bool SPECIALTRIGGERED = std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == &k; }) != m_vPressedSpecialBinds.end(); const bool IGNORECONDITIONS = @@ -2022,6 +2023,157 @@ void CKeybindManager::pass(std::string regexp) { g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), SL); } +void CKeybindManager::sendshortcut(std::string args) { + // args=<NEW_MODKEYS><NEW_KEY>[,WINDOW_RULES] + const auto ARGS = CVarList(args, 3); + if (ARGS.size() != 3) { + Debug::log(ERR, "sendshortcut: invalid args"); + return; + } + + const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]); + const auto KEY = ARGS[1]; + uint32_t keycode = 0; + bool isMouse = 0; + + // similar to parseKey in ConfigManager + if (isNumber(KEY) && std::stoi(KEY) > 9) + keycode = std::stoi(KEY); + else if (KEY.compare(0, 5, "code:") == 0 && isNumber(KEY.substr(5))) + keycode = std::stoi(KEY.substr(5)); + else if (KEY.compare(0, 6, "mouse:") == 0 && isNumber(KEY.substr(6))) { + keycode = std::stoi(KEY.substr(6)); + isMouse = 1; + if (keycode < 272) { + Debug::log(ERR, "sendshortcut: invalid mouse button"); + return; + } + } else { + + // here, we need to find the keycode from the key name + // this is not possible through xkb's lib, so we need to iterate through all keycodes + // once found, we save it to the cache + + const auto KEYSYM = xkb_keysym_from_name(KEY.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + keycode = 0; + + const auto KB = g_pSeatManager->keyboard; + + if (!KB) { + Debug::log(ERR, "sendshortcut: no kb"); + return; + } + + const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY); + + if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) { + xkb_keymap* km = KB->wlr()->keymap; + xkb_state* ks = KB->xkbTranslationState; + + xkb_keycode_t keycode_min, keycode_max; + keycode_min = xkb_keymap_min_keycode(km); + keycode_max = xkb_keymap_max_keycode(km); + + for (xkb_keycode_t kc = keycode_min; kc <= keycode_max; ++kc) { + xkb_keysym_t sym = xkb_state_key_get_one_sym(ks, kc); + + if (sym == KEYSYM) { + keycode = kc; + g_pKeybindManager->m_mKeyToCodeCache[KEYPAIRSTRING] = keycode; + } + } + + if (!keycode) { + Debug::log(ERR, "sendshortcut: key not found"); + return; + } + + } else + keycode = g_pKeybindManager->m_mKeyToCodeCache[KEYPAIRSTRING]; + } + + if (!keycode) { + Debug::log(ERR, "sendshortcut: invalid key"); + return; + } + + const std::string regexp = ARGS[2]; + PHLWINDOW PWINDOW = nullptr; + const auto LASTSURFACE = g_pCompositor->m_pLastFocus; + + //if regexp is not empty, send shortcut to current window + //else, dont change focus + if (regexp != "") { + PWINDOW = g_pCompositor->getWindowByRegex(regexp); + + if (!PWINDOW) { + Debug::log(ERR, "sendshortcut: window not found"); + return; + } + + if (!g_pSeatManager->keyboard) { + Debug::log(ERR, "No kb in sendshortcut?"); + return; + } + + if (!isMouse) + g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface.wlr()); + else + g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), {1, 1}); + } + + //copied the rest from pass and modified it + // if wl -> xwl, activate destination + if (PWINDOW && PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsX11) + g_pXWaylandManager->activateSurface(PWINDOW->m_pWLSurface.wlr(), true); + // if xwl -> xwl, send to current. Timing issues make this not work. + if (PWINDOW && PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11) + PWINDOW = nullptr; + + g_pSeatManager->sendKeyboardMods(MOD, 0, 0, 0); + + if (g_pKeybindManager->m_iPassPressed == 1) { + if (!isMouse) + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); + else + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED); + } else if (g_pKeybindManager->m_iPassPressed == 0) { + if (!isMouse) + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); + else + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED); + } else { + // dynamic call of the dispatcher + if (!isMouse) { + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); + } else { + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED); + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED); + } + } + + if (!PWINDOW) + return; + + if (PWINDOW->m_bIsX11) { //xwayland hack, see pass + if (!isMouse) { + g_pSeatManager->state.keyboardFocus = nullptr; + g_pSeatManager->state.keyboardFocusResource.reset(); + } else { + g_pSeatManager->state.pointerFocus = nullptr; + g_pSeatManager->state.pointerFocusResource.reset(); + } + } + + const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); + + if (!isMouse) + g_pSeatManager->setKeyboardFocus(LASTSURFACE); + else + g_pSeatManager->setPointerFocus(LASTSURFACE, SL); +} + void CKeybindManager::layoutmsg(std::string msg) { SLayoutMessageHeader hd = {g_pCompositor->m_pLastWindow.lock()}; g_pLayoutManager->getCurrentLayout()->layoutMessage(hd, msg); |
