mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-26 01:31:54 -07:00
keybinds: Added new dispatcher (sendshortcut) (#6174)
This commit is contained in:
@@ -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);
|
||||
|
Reference in New Issue
Block a user