diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2026-04-26 15:16:36 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-26 15:16:36 +0100 |
| commit | 5ba33f846129f3e6c0505b19f94634b24505e828 (patch) | |
| tree | aaacabe678006040c342935481a86607c66607fd /src/managers/KeybindManager.cpp | |
| parent | 329b2b356dd92ac07f4e2aa69cbce82ee9ba9d19 (diff) | |
config/lua: init lua config manager, use lua if available (#13817)
Adds a new lua config manager, which will automatically be used if there is a lua config present.
Diffstat (limited to 'src/managers/KeybindManager.cpp')
| -rw-r--r-- | src/managers/KeybindManager.cpp | 2558 |
1 files changed, 128 insertions, 2430 deletions
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9bd7ec97..df03f920 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1,54 +1,26 @@ #include "../config/ConfigValue.hpp" -#include "../config/legacy/ConfigManager.hpp" -#include "../config/shared/monitor/MonitorRuleManager.hpp" +#include "../config/ConfigManager.hpp" +#include "../config/legacy/DispatcherTranslator.hpp" +#include "../config/shared/actions/ConfigActions.hpp" #include "../devices/IKeyboard.hpp" -#include "../desktop/state/FocusState.hpp" -#include "../desktop/history/WindowHistoryTracker.hpp" -#include "../desktop/history/WorkspaceHistoryTracker.hpp" #include "../managers/SeatManager.hpp" -#include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" -#include "../protocols/GlobalShortcuts.hpp" -#include "../protocols/IdleNotify.hpp" #include "../protocols/core/DataDevice.hpp" -#include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "../errorOverlay/Overlay.hpp" #include "KeybindManager.hpp" #include "PointerManager.hpp" #include "Compositor.hpp" -#include "TokenManager.hpp" #include "eventLoop/EventLoopManager.hpp" #include "debug/log/Logger.hpp" #include "../managers/input/InputManager.hpp" -#include "../managers/animation/DesktopAnimationManager.hpp" -#include "../managers/EventManager.hpp" -#include "../render/Renderer.hpp" -#include "../errorOverlay/Overlay.hpp" -#include "../config/ConfigManager.hpp" -#include "../desktop/rule/windowRule/WindowRule.hpp" -#include "../desktop/rule/Engine.hpp" -#include "../desktop/view/Group.hpp" #include "../layout/LayoutManager.hpp" -#include "../layout/target/WindowTarget.hpp" -#include "../layout/space/Space.hpp" -#include "../layout/algorithm/Algorithm.hpp" -#include "../layout/algorithm/tiled/master/MasterAlgorithm.hpp" -#include "../layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp" #include "../event/EventBus.hpp" -#include "../config/supplementary/executor/Executor.hpp" -#include <optional> -#include <iterator> #include <string> -#include <string_view> #include <cstring> #include <hyprutils/string/String.hpp> -#include <hyprutils/string/ConstVarList.hpp> -#include <hyprutils/string/VarList.hpp> -#include <hyprutils/string/VarList2.hpp> -#include <hyprutils/os/FileDescriptor.hpp> using namespace Hyprutils::String; -using namespace Hyprutils::OS; #include <sys/ioctl.h> #include <fcntl.h> @@ -63,84 +35,86 @@ using namespace Hyprutils::OS; CKeybindManager::CKeybindManager() { // initialize all dispatchers - - m_dispatchers["exec"] = spawn; - m_dispatchers["execr"] = spawnRaw; - m_dispatchers["killactive"] = closeActive; - m_dispatchers["forcekillactive"] = killActive; - m_dispatchers["closewindow"] = closeWindow; - m_dispatchers["killwindow"] = killWindow; - m_dispatchers["signal"] = signalActive; - m_dispatchers["signalwindow"] = signalWindow; - m_dispatchers["togglefloating"] = toggleActiveFloating; - m_dispatchers["setfloating"] = setActiveFloating; - m_dispatchers["settiled"] = setActiveTiled; - m_dispatchers["workspace"] = changeworkspace; - m_dispatchers["renameworkspace"] = renameWorkspace; - m_dispatchers["fullscreen"] = fullscreenActive; - m_dispatchers["fullscreenstate"] = fullscreenStateActive; - m_dispatchers["movetoworkspace"] = moveActiveToWorkspace; - m_dispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent; - m_dispatchers["pseudo"] = toggleActivePseudo; - m_dispatchers["movefocus"] = moveFocusTo; - m_dispatchers["movewindow"] = moveActiveTo; - m_dispatchers["swapwindow"] = swapActive; - m_dispatchers["centerwindow"] = centerWindow; - m_dispatchers["togglegroup"] = toggleGroup; - m_dispatchers["changegroupactive"] = changeGroupActive; - m_dispatchers["movegroupwindow"] = moveGroupWindow; - m_dispatchers["focusmonitor"] = focusMonitor; - m_dispatchers["movecursortocorner"] = moveCursorToCorner; - m_dispatchers["movecursor"] = moveCursor; - m_dispatchers["workspaceopt"] = workspaceOpt; - m_dispatchers["exit"] = exitHyprland; - m_dispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; - m_dispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor; - m_dispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; - m_dispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; - m_dispatchers["forcerendererreload"] = forceRendererReload; - m_dispatchers["resizeactive"] = resizeActive; - m_dispatchers["moveactive"] = moveActive; - m_dispatchers["cyclenext"] = circleNext; - m_dispatchers["focuswindowbyclass"] = focusWindow; - m_dispatchers["focuswindow"] = focusWindow; - m_dispatchers["tagwindow"] = tagWindow; - m_dispatchers["toggleswallow"] = toggleSwallow; - m_dispatchers["submap"] = setSubmap; - m_dispatchers["pass"] = pass; - m_dispatchers["sendshortcut"] = sendshortcut; - m_dispatchers["sendkeystate"] = sendkeystate; - m_dispatchers["layoutmsg"] = layoutmsg; - m_dispatchers["dpms"] = dpms; - m_dispatchers["movewindowpixel"] = moveWindow; - m_dispatchers["resizewindowpixel"] = resizeWindow; - m_dispatchers["swapnext"] = swapnext; - m_dispatchers["swapactiveworkspaces"] = swapActiveWorkspaces; - m_dispatchers["pin"] = pinActive; - m_dispatchers["mouse"] = mouse; - m_dispatchers["bringactivetotop"] = bringActiveToTop; - m_dispatchers["alterzorder"] = alterZOrder; - m_dispatchers["focusurgentorlast"] = focusUrgentOrLast; - m_dispatchers["focuscurrentorlast"] = focusCurrentOrLast; - m_dispatchers["lockgroups"] = lockGroups; - m_dispatchers["lockactivegroup"] = lockActiveGroup; - m_dispatchers["moveintogroup"] = moveIntoGroup; - m_dispatchers["moveintoorcreategroup"] = moveIntoOrCreateGroup; - m_dispatchers["moveoutofgroup"] = moveOutOfGroup; - m_dispatchers["movewindoworgroup"] = moveWindowOrGroup; - m_dispatchers["setignoregrouplock"] = setIgnoreGroupLock; - m_dispatchers["denywindowfromgroup"] = denyWindowFromGroup; - m_dispatchers["event"] = event; - m_dispatchers["global"] = global; - m_dispatchers["setprop"] = setProp; - m_dispatchers["forceidle"] = forceIdle; + // populate m_dispatchers from the legacy translator + for (const auto& name : {"exec", + "execr", + "killactive", + "forcekillactive", + "closewindow", + "killwindow", + "signal", + "signalwindow", + "togglefloating", + "setfloating", + "settiled", + "workspace", + "renameworkspace", + "fullscreen", + "fullscreenstate", + "movetoworkspace", + "movetoworkspacesilent", + "pseudo", + "movefocus", + "movewindow", + "swapwindow", + "centerwindow", + "togglegroup", + "changegroupactive", + "movegroupwindow", + "focusmonitor", + "movecursortocorner", + "movecursor", + "workspaceopt", + "exit", + "movecurrentworkspacetomonitor", + "focusworkspaceoncurrentmonitor", + "moveworkspacetomonitor", + "togglespecialworkspace", + "forcerendererreload", + "resizeactive", + "moveactive", + "cyclenext", + "focuswindowbyclass", + "focuswindow", + "tagwindow", + "toggleswallow", + "submap", + "pass", + "sendshortcut", + "sendkeystate", + "layoutmsg", + "dpms", + "movewindowpixel", + "resizewindowpixel", + "swapnext", + "swapactiveworkspaces", + "pin", + "mouse", + "bringactivetotop", + "alterzorder", + "focusurgentorlast", + "focuscurrentorlast", + "lockgroups", + "lockactivegroup", + "moveintogroup", + "moveoutofgroup", + "movewindoworgroup", + "moveintoorcreategroup", + "setignoregrouplock", + "denywindowfromgroup", + "event", + "global", + "setprop", + "forceidle"}) { + m_dispatchers[name] = [n = std::string(name)](std::string args) -> SDispatchResult { return Config::Legacy::translator()->run(n, args); }; + } m_scrollTimer.reset(); m_longPressTimer = makeShared<CEventLoopTimer>( std::nullopt, [this](SP<CEventLoopTimer> self, void* data) { - if (!m_lastLongPressKeybind || g_pSeatManager->m_keyboard.expired()) + if (!m_lastLongPressKeybind || !m_lastLongPressKeybind->enabled || g_pSeatManager->m_keyboard.expired()) return; const auto PACTIVEKEEB = g_pSeatManager->m_keyboard.lock(); @@ -157,6 +131,8 @@ CKeybindManager::CKeybindManager() { m_repeatKeyTimer = makeShared<CEventLoopTimer>( std::nullopt, [this](SP<CEventLoopTimer> self, void* data) { + std::erase_if(m_activeKeybinds, [](const auto& k) { return !k || !k->enabled; }); + if (m_activeKeybinds.empty() || g_pSeatManager->m_keyboard.expired()) return; @@ -165,6 +141,9 @@ CKeybindManager::CKeybindManager() { return; for (const auto& k : m_activeKeybinds) { + if (!k || !k->enabled) + continue; + const auto DISPATCHER = g_pKeybindManager->m_dispatchers.find(k->handler); Log::logger->log(Log::DEBUG, "Keybind repeat triggered, calling dispatcher."); @@ -201,11 +180,14 @@ CKeybindManager::~CKeybindManager() { } } -void CKeybindManager::addKeybind(SKeybind kb) { - m_keybinds.emplace_back(makeShared<SKeybind>(kb)); +SP<SKeybind> CKeybindManager::addKeybind(SKeybind kb) { + const auto KEYBIND = makeShared<SKeybind>(kb); + m_keybinds.emplace_back(KEYBIND); m_activeKeybinds.clear(); m_lastLongPressKeybind.reset(); + + return KEYBIND; } void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { @@ -316,93 +298,6 @@ bool CKeybindManager::ensureMouseBindState() { return false; } -static void updateRelativeCursorCoords() { - static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps"); - - if (*PNOWARPS) - return; - - if (Desktop::focusState()->window()) - Desktop::focusState()->window()->m_relativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - Desktop::focusState()->window()->m_position; -} - -bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { - if (!monitor) - return false; - - const auto LASTMONITOR = Desktop::focusState()->monitor(); - if (!LASTMONITOR) - return false; - if (LASTMONITOR == monitor) { - Log::logger->log(Log::DEBUG, "Tried to move to active monitor"); - return false; - } - - static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse"); - static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps"); - - const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; - const auto PNEWMAINWORKSPACE = monitor->m_activeWorkspace; - - g_pInputManager->unconstrainMouse(); - - const auto PNEWWORKSPACE = monitor->m_activeSpecialWorkspace ? monitor->m_activeSpecialWorkspace : PNEWMAINWORKSPACE; - - const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow(); - if (PNEWWINDOW) { - updateRelativeCursorCoords(); - Desktop::focusState()->fullWindowFocus(PNEWWINDOW, Desktop::FOCUS_REASON_KEYBIND); - PNEWWINDOW->warpCursor(); - - if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) { - g_pInputManager->m_forcedFocus = PNEWWINDOW; - g_pInputManager->simulateMouseMovement(); - g_pInputManager->m_forcedFocus.reset(); - } - } else { - Desktop::focusState()->rawWindowFocus(nullptr, Desktop::FOCUS_REASON_KEYBIND); - g_pCompositor->warpCursorTo(monitor->middle()); - } - Desktop::focusState()->rawMonitorFocus(monitor); - - return true; -} - -void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool forceFSCycle) { - static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse"); - static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps"); - - const auto PLASTWINDOW = Desktop::focusState()->window(); - - if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO) - return; - - // remove constraints - g_pInputManager->unconstrainMouse(); - - if (PLASTWINDOW && PLASTWINDOW->m_workspace == PWINDOWTOCHANGETO->m_workspace && PLASTWINDOW->isFullscreen()) - Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, Desktop::FOCUS_REASON_KEYBIND, nullptr, forceFSCycle); - else { - updateRelativeCursorCoords(); - Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, Desktop::FOCUS_REASON_KEYBIND, nullptr, forceFSCycle); - PWINDOWTOCHANGETO->warpCursor(); - - // Move mouse focus to the new window if required by current follow_mouse and warp modes - if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) { - g_pInputManager->m_forcedFocus = PWINDOWTOCHANGETO; - g_pInputManager->simulateMouseMovement(); - g_pInputManager->m_forcedFocus.reset(); - } - - if (PLASTWINDOW && PLASTWINDOW->m_monitor != PWINDOWTOCHANGETO->m_monitor) { - // event - const auto PNEWMON = PWINDOWTOCHANGETO->m_monitor.lock(); - - Desktop::focusState()->rawMonitorFocus(PNEWMON); - } - } -}; - bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { if (!g_pCompositor->m_sessionActive || g_pCompositor->m_unsafeState) { m_pressedKeys.clear(); @@ -437,9 +332,9 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { const auto MODS = g_pInputManager->getModsFromAllKBs(); - m_timeLastMs = e.timeMs; - m_lastCode = KEYCODE; - m_lastMouseCode = 0; + Config::Actions::state()->m_timeLastMs = e.timeMs; + Config::Actions::state()->m_lastCode = KEYCODE; + Config::Actions::state()->m_lastMouseCode = 0; bool mouseBindWasActive = ensureMouseBindState(); @@ -448,7 +343,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { .keycode = KEYCODE, .modmaskAtPressTime = MODS, .sent = true, - .submapAtPress = m_currentSelectedSubmap, + .submapAtPress = SSubmap{.name = Config::Actions::state()->m_currentSubmap}, .mousePosAtPress = g_pInputManager->getMouseCoordsInternal(), }; @@ -495,7 +390,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e, SP<IPointer> pointer) { const auto MODS = g_pInputManager->getModsFromAllKBs(); - static auto PDELAY = CConfigValue<Hyprlang::INT>("binds:scroll_event_delay"); + static auto PDELAY = CConfigValue<Config::INTEGER>("binds:scroll_event_delay"); if (m_scrollTimer.getMillis() < *PDELAY) return true; // timer hasn't passed yet! @@ -528,9 +423,9 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e, SP<IPointer> bool suppressEvent = false; - m_lastMouseCode = e.button; - m_lastCode = 0; - m_timeLastMs = e.timeMs; + Config::Actions::state()->m_lastMouseCode = e.button; + Config::Actions::state()->m_lastCode = 0; + Config::Actions::state()->m_timeLastMs = e.timeMs; bool mouseBindWasActive = ensureMouseBindState(); @@ -593,15 +488,20 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true, nullptr, nullptr); } -eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set<xkb_keysym_t> keybindKeysyms, const std::set<xkb_keysym_t> pressedKeysyms) { +eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::vector<xkb_keysym_t> keybindKeysyms, const std::set<xkb_keysym_t> pressedKeysyms) { // Returns whether two sets of keysyms are equal, partially equal, or not // matching. (Partially matching means that pressed is a subset of bound) std::set<xkb_keysym_t> boundKeysNotPressed; std::set<xkb_keysym_t> pressedKeysNotBound; - std::ranges::set_difference(keybindKeysyms, pressedKeysyms, std::inserter(boundKeysNotPressed, boundKeysNotPressed.begin())); - std::ranges::set_difference(pressedKeysyms, keybindKeysyms, std::inserter(pressedKeysNotBound, pressedKeysNotBound.begin())); + std::set<xkb_keysym_t> symsKb; + for (const auto& k : keybindKeysyms) { + symsKb.emplace(k); + } + + std::ranges::set_difference(symsKb, pressedKeysyms, std::inserter(boundKeysNotPressed, boundKeysNotPressed.begin())); + std::ranges::set_difference(pressedKeysyms, symsKb, std::inserter(pressedKeysNotBound, pressedKeysNotBound.begin())); if (boundKeysNotPressed.empty() && pressedKeysNotBound.empty()) return MK_FULL_MATCH; @@ -620,16 +520,18 @@ eMultiKeyCase CKeybindManager::mkBindMatches(const SP<SKeybind> keybind) { } SSubmap CKeybindManager::getCurrentSubmap() { - return m_currentSelectedSubmap; + return SSubmap{.name = Config::Actions::state()->m_currentSubmap}; } SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed, SP<IKeyboard> keyboard, SP<IHID> device) { - static auto PDISABLEINHIBIT = CConfigValue<Hyprlang::INT>("binds:disable_keybind_grabbing"); - static auto PDRAGTHRESHOLD = CConfigValue<Hyprlang::INT>("binds:drag_threshold"); + static auto PDISABLEINHIBIT = CConfigValue<Config::INTEGER>("binds:disable_keybind_grabbing"); + static auto PDRAGTHRESHOLD = CConfigValue<Config::INTEGER>("binds:drag_threshold"); bool found = false; SDispatchResult res; + std::erase_if(m_pressedSpecialBinds, [](const auto& k) { return !k || !k->enabled; }); + // Skip keysym tracking for events with no keysym (e.g., scroll wheel events). // Scroll events have keysym=0 and are always "pressed" (never released), // so without this check, 0 gets inserted into m_mkKeys and never removed, @@ -657,10 +559,13 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP if (!k->dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) continue; + if (!k->enabled) + continue; + if (!k->locked && g_pSessionLockManager->isSessionLocked()) continue; - if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || (k->submap != m_currentSelectedSubmap && !k->submapUniversal) || k->shadowed)) + if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || (k->submap.name != Config::Actions::state()->m_currentSubmap && !k->submapUniversal) || k->shadowed)) continue; if (device) { @@ -674,6 +579,11 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP case MK_PARTIAL_MATCH: found = true; continue; case MK_FULL_MATCH: found = true; } + } else if (!k->sMkKeys.empty() && key.keyName.empty()) { + if (!k->release && mkKeysymSetMatches(k->sMkKeys, m_mkKeys) != MK_FULL_MATCH) + continue; + if (key.keysym != k->sMkKeys.back()) + continue; } else if (!key.keyName.empty()) { if (key.keyName != k->key) continue; @@ -681,7 +591,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP if (key.keycode != k->keycode) continue; } else if (k->catchAll) { - if (found || key.submapAtPress != m_currentSelectedSubmap) + if (found || key.submapAtPress.name != Config::Actions::state()->m_currentSubmap) continue; } else { // in this case, we only have the keysym to go off of for this keybind, and it's invalid @@ -768,7 +678,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP // call the dispatcher Log::logger->log(Log::DEBUG, "Keybind triggered, calling dispatcher ({}, {}, {}, {})", modmask, key.keyName, key.keysym, DISPATCHER->first); - m_passPressed = sc<int>(pressed); + Config::Actions::state()->m_passPressed = sc<int>(pressed); // if the dispatchers says to pass event then we will if (k->handler == "mouse") @@ -776,14 +686,14 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP else res = DISPATCHER->second(k->arg); - m_passPressed = -1; + Config::Actions::state()->m_passPressed = -1; if (k->handler == "submap") { found = true; // don't process keybinds on submap change. break; } - if (k->handler != "submap" && !k->submap.reset.empty()) - setSubmap(k->submap.reset); + if (k->handler != "submap" && !k->submap.reset.empty()) // NOLINTNEXTLINE + Config::Actions::setSubmap(k->submap.reset); } if (pressed && k->repeat) { @@ -819,6 +729,11 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3 for (auto& k : m_keybinds) { + if (!k->enabled) { + k->shadowed = false; + continue; + } + bool shadow = false; if (k->handler == "global" || k->transparent) @@ -896,1629 +811,10 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { return false; } -// Dispatchers -SDispatchResult CKeybindManager::spawn(std::string args) { - const auto PROC = Config::Supplementary::executor()->spawn(args); - if (!PROC.has_value()) - return {.success = false, .error = std::format("Failed to start process. No closing bracket in exec rule. {}", args)}; - return {.success = PROC.value() > 0, .error = std::format("Failed to start process {}", args)}; -} - -SDispatchResult CKeybindManager::spawnRaw(std::string args) { - const auto PROC = Config::Supplementary::executor()->spawnRaw(args); - return {.success = PROC && *PROC > 0, .error = std::format("Failed to start process {}", args)}; -} - -SDispatchResult CKeybindManager::killActive(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "killActive: no window found"); - return {.success = false, .error = "killActive: no window found"}; - } - - kill(PWINDOW->getPID(), SIGKILL); - - return {}; -} - -SDispatchResult CKeybindManager::closeActive(std::string args) { - if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_closeableSince > Time::steadyNow()) - return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"}; - - g_pCompositor->closeWindow(Desktop::focusState()->window()); - - return {}; -} - -SDispatchResult CKeybindManager::closeWindow(std::string args) { - const auto PWINDOW = g_pCompositor->getWindowByRegex(args); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "closeWindow: no window found"); - return {.success = false, .error = "closeWindow: no window found"}; - } - - if (PWINDOW->m_closeableSince > Time::steadyNow()) - return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"}; - - g_pCompositor->closeWindow(PWINDOW); - - return {}; -} - -SDispatchResult CKeybindManager::killWindow(std::string args) { - const auto PWINDOW = g_pCompositor->getWindowByRegex(args); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "killWindow: no window found"); - return {.success = false, .error = "killWindow: no window found"}; - } - - kill(PWINDOW->getPID(), SIGKILL); - - return {}; -} - -SDispatchResult CKeybindManager::signalActive(std::string args) { - if (!isNumber(args)) - return {.success = false, .error = "signalActive: signal has to be int"}; - - try { - const auto SIGNALNUM = std::stoi(args); - if (SIGNALNUM < 1 || SIGNALNUM > 31) { - Log::logger->log(Log::ERR, "signalActive: invalid signal number {}", SIGNALNUM); - return {.success = false, .error = std::format("signalActive: invalid signal number {}", SIGNALNUM)}; - } - kill(Desktop::focusState()->window()->getPID(), SIGNALNUM); - } catch (const std::exception& e) { - Log::logger->log(Log::ERR, "signalActive: invalid signal format \"{}\"", args); - return {.success = false, .error = std::format("signalActive: invalid signal format \"{}\"", args)}; - } - - kill(Desktop::focusState()->window()->getPID(), std::stoi(args)); - - return {}; -} - -SDispatchResult CKeybindManager::signalWindow(std::string args) { - const auto WINDOWREGEX = args.substr(0, args.find_first_of(',')); - const auto SIGNAL = args.substr(args.find_first_of(',') + 1); - - const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "signalWindow: no window"); - return {.success = false, .error = "signalWindow: no window"}; - } - - if (!std::ranges::all_of(SIGNAL, ::isdigit)) - return {.success = false, .error = "signalWindow: signal has to be int"}; - - try { - const auto SIGNALNUM = std::stoi(SIGNAL); - if (SIGNALNUM < 1 || SIGNALNUM > 31) { - Log::logger->log(Log::ERR, "signalWindow: invalid signal number {}", SIGNALNUM); - return {.success = false, .error = std::format("signalWindow: invalid signal number {}", SIGNALNUM)}; - } - kill(PWINDOW->getPID(), SIGNALNUM); - } catch (const std::exception& e) { - Log::logger->log(Log::ERR, "signalWindow: invalid signal format \"{}\"", SIGNAL); - return {.success = false, .error = std::format("signalWindow: invalid signal format \"{}\"", SIGNAL)}; - } - - return {}; -} - void CKeybindManager::clearKeybinds() { m_keybinds.clear(); } -static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional<bool> floatState) { - PHLWINDOW PWINDOW = nullptr; - - if (args != "active" && args.length() > 1) - PWINDOW = g_pCompositor->getWindowByRegex(args); - else - PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - if (floatState.has_value() && floatState == PWINDOW->m_isFloating) - return {}; - - // remove drag status - if (g_layoutManager->dragController()->target()) - CKeybindManager::changeMouseBindMode(MBIND_INVALID); - - g_layoutManager->changeFloatingMode(PWINDOW->layoutTarget()); - - if (PWINDOW->m_isFloating) - g_pCompositor->changeWindowZOrder(PWINDOW, true); - - if (PWINDOW->m_workspace) { - PWINDOW->m_workspace->updateWindows(); - PWINDOW->m_workspace->updateWindowData(); - } - - g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - - return {}; -} - -SDispatchResult CKeybindManager::toggleActiveFloating(std::string args) { - return toggleActiveFloatingCore(args, std::nullopt); -} - -SDispatchResult CKeybindManager::setActiveFloating(std::string args) { - return toggleActiveFloatingCore(args, true); -} - -SDispatchResult CKeybindManager::setActiveTiled(std::string args) { - return toggleActiveFloatingCore(args, false); -} - -SDispatchResult CKeybindManager::centerWindow(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW || !PWINDOW->m_isFloating || PWINDOW->isFullscreen()) - return {.success = false, .error = "No floating window found"}; - - const auto PMONITOR = PWINDOW->m_monitor.lock(); - - PWINDOW->layoutTarget()->setPositionGlobal(CBox{PMONITOR->logicalBoxMinusReserved().middle() - PWINDOW->m_realSize->goal() / 2.F, PWINDOW->layoutTarget()->position().size()}); - - return {}; -} - -SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) { - PHLWINDOW PWINDOW = nullptr; - - if (args != "active" && args.length() > 1) - PWINDOW = g_pCompositor->getWindowByRegex(args); - else - PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - PWINDOW->layoutTarget()->setPseudo(!PWINDOW->layoutTarget()->isPseudo()); - - return {}; -} - -static SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE, PHLMONITORREF PMONITOR) { - if (!args.starts_with("previous")) { - return getWorkspaceIDNameFromString(args); - } - - const bool PER_MON = args.contains("_per_monitor"); - const SWorkspaceIDName PPREVWS = PER_MON ? Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE, PMONITOR.lock()) : - Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE); - // Do nothing if there's no previous workspace, otherwise switch to it. - if (PPREVWS.id == -1 || PPREVWS.id == PCURRENTWORKSPACE->m_id) { - Log::logger->log(Log::DEBUG, "No previous workspace to change to"); - return {.id = WORKSPACE_NOT_CHANGED}; - } - - if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) { - return {.id = PWORKSPACETOCHANGETO->m_id, .name = PWORKSPACETOCHANGETO->m_name}; - } - - return {.id = PPREVWS.id, .name = PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; -} - -SDispatchResult CKeybindManager::changeworkspace(std::string args) { - // Workspace_back_and_forth being enabled means that an attempt to switch to - // the current workspace will instead switch to the previous. - static auto PBACKANDFORTH = CConfigValue<Hyprlang::INT>("binds:workspace_back_and_forth"); - static auto PWORKSPACECENTERON = CConfigValue<Hyprlang::INT>("binds:workspace_center_on"); - static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("binds:hide_special_on_workspace_change"); - - const auto PMONITOR = Desktop::focusState()->monitor(); - - if (!PMONITOR) - return {.success = false, .error = "Last monitor not found"}; - - const auto PCURRENTWORKSPACE = PMONITOR->m_activeWorkspace; - const bool EXPLICITPREVIOUS = args.contains("previous"); - - const auto& [workspaceToChangeTo, workspaceName, isAutoID] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE, PMONITOR); - if (workspaceToChangeTo == WORKSPACE_INVALID) { - Log::logger->log(Log::ERR, "Error in changeworkspace, invalid value"); - return {.success = false, .error = "Error in changeworkspace, invalid value"}; - } - - if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) - return {}; - - const SWorkspaceIDName PPREVWS = args.contains("_per_monitor") ? Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE, PMONITOR) : - Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE); - - const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_id; - if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PPREVWS.id == -1)) { - if (*PHIDESPECIALONWORKSPACECHANGE) - PMONITOR->setSpecialWorkspace(nullptr); - - return {.success = false, .error = "Previous workspace doesn't exist"}; - } - - g_pInputManager->unconstrainMouse(); - g_pInputManager->m_emptyFocusCursorSet = false; - - auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo); - if (!pWorkspaceToChangeTo) - pWorkspaceToChangeTo = - g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo, PMONITOR->m_id, BISWORKSPACECURRENT ? PPREVWS.name : workspaceName); - - if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_isSpecialWorkspace) { - PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo); - g_pInputManager->simulateMouseMovement(); - return {}; - } - - g_pInputManager->releaseAllMouseButtons(); - - const auto PMONITORWORKSPACEOWNER = PMONITOR == pWorkspaceToChangeTo->m_monitor ? PMONITOR : pWorkspaceToChangeTo->m_monitor.lock(); - - if (!PMONITORWORKSPACEOWNER) - return {.success = false, .error = "Workspace to switch to has no monitor"}; - - updateRelativeCursorCoords(); - - Desktop::focusState()->rawMonitorFocus(PMONITORWORKSPACEOWNER); - - if (*PHIDESPECIALONWORKSPACECHANGE) - PMONITORWORKSPACEOWNER->setSpecialWorkspace(nullptr); - PMONITORWORKSPACEOWNER->changeWorkspace(pWorkspaceToChangeTo, false, true); - - if (PMONITOR != PMONITORWORKSPACEOWNER) { - Vector2D middle = PMONITORWORKSPACEOWNER->middle(); - if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) { - Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_KEYBIND); - if (*PWORKSPACECENTERON == 1) - middle = PLAST->middle(); - } - g_pCompositor->warpCursorTo(middle); - } - - if (!g_pInputManager->m_lastFocusOnLS) { - if (Desktop::focusState()->surface()) - g_pInputManager->sendMotionEventsToFocused(); - else - g_pInputManager->simulateMouseMovement(); - } - - const static auto PWARPONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("cursor:warp_on_change_workspace"); - - if (*PWARPONWORKSPACECHANGE > 0) { - auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); - auto HLSurface = Desktop::View::CWLSurface::fromResource(g_pSeatManager->m_state.pointerFocus.lock()); - - if (PLAST && (!HLSurface || HLSurface->view()->type() == Desktop::View::VIEW_TYPE_WINDOW)) - PLAST->warpCursor(*PWARPONWORKSPACECHANGE == 2); - } - - return {}; -} - -SDispatchResult CKeybindManager::fullscreenActive(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - const auto ARGS = CConstVarList(args, 2, ' '); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - const eFullscreenMode MODE = ARGS.size() > 0 && ARGS[0] == "1" ? FSMODE_MAXIMIZED : FSMODE_FULLSCREEN; - - if (ARGS.size() <= 1 || ARGS[1] == "toggle") { - if (PWINDOW->isEffectiveInternalFSMode(MODE)) - g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); - else - g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE); - } else { - if (ARGS[1] == "set") - g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE); - else if (ARGS[1] == "unset") - g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); - } - - return {}; -} - -SDispatchResult CKeybindManager::fullscreenStateActive(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - const auto ARGS = CVarList(args, 3, ' '); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - PWINDOW->m_ruleApplicator->syncFullscreenOverride(Desktop::Types::COverridableVar(false, Desktop::Types::PRIORITY_SET_PROP)); - - int internalMode, clientMode; - try { - internalMode = std::stoi(ARGS[0]); - } catch (std::exception& e) { internalMode = -1; } - try { - clientMode = std::stoi(ARGS[1]); - } catch (std::exception& e) { clientMode = -1; } - - const Desktop::View::SFullscreenState STATE = - Desktop::View::SFullscreenState{.internal = (internalMode != -1 ? sc<eFullscreenMode>(internalMode) : PWINDOW->m_fullscreenState.internal), - .client = (clientMode != -1 ? sc<eFullscreenMode>(clientMode) : PWINDOW->m_fullscreenState.client)}; - - if (ARGS.size() <= 2 || ARGS[2] == "toggle") { - if (internalMode != -1 && clientMode != -1 && PWINDOW->m_fullscreenState.internal == STATE.internal && PWINDOW->m_fullscreenState.client == STATE.client) - g_pCompositor->setWindowFullscreenState(PWINDOW, Desktop::View::SFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE}); - else if (internalMode != -1 && clientMode == -1 && PWINDOW->m_fullscreenState.internal == STATE.internal) - g_pCompositor->setWindowFullscreenState(PWINDOW, Desktop::View::SFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_fullscreenState.client}); - else if (internalMode == -1 && clientMode != -1 && PWINDOW->m_fullscreenState.client == STATE.client) - g_pCompositor->setWindowFullscreenState(PWINDOW, Desktop::View::SFullscreenState{.internal = PWINDOW->m_fullscreenState.internal, .client = FSMODE_NONE}); - else - g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); - } else if (ARGS[2] == "set") { - g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); - } - - PWINDOW->m_ruleApplicator->syncFullscreenOverride( - Desktop::Types::COverridableVar(PWINDOW->m_fullscreenState.internal == PWINDOW->m_fullscreenState.client, Desktop::Types::PRIORITY_SET_PROP)); - - return {}; -} - -SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { - - PHLWINDOW PWINDOW = nullptr; - - if (args.contains(',')) { - PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1)); - args = args.substr(0, args.find_last_of(',')); - } else { - PWINDOW = Desktop::focusState()->window(); - } - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - const auto& [WORKSPACEID, workspaceName, isAutoID] = getWorkspaceIDNameFromString(args); - if (WORKSPACEID == WORKSPACE_INVALID) { - Log::logger->log(Log::DEBUG, "Invalid workspace in moveActiveToWorkspace"); - return {.success = false, .error = "Invalid workspace in moveActiveToWorkspace"}; - } - - if (WORKSPACEID == PWINDOW->workspaceID()) { - Log::logger->log(Log::DEBUG, "Not moving to workspace because it didn't change."); - return {.success = false, .error = "Not moving to workspace because it didn't change."}; - } - - auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); - PHLMONITOR pMonitor = nullptr; - const auto POLDWS = PWINDOW->m_workspace; - - updateRelativeCursorCoords(); - - g_pHyprRenderer->damageWindow(PWINDOW); - - if (pWorkspace) { - const auto FULLSCREENMODE = PWINDOW->m_fullscreenState.internal; - g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); - pMonitor = pWorkspace->m_monitor.lock(); - Desktop::focusState()->rawMonitorFocus(pMonitor); - g_pCompositor->setWindowFullscreenInternal(PWINDOW, FULLSCREENMODE); - } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); - pMonitor = pWorkspace->m_monitor.lock(); - g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); - } - - POLDWS->m_lastFocusedWindow = POLDWS->getFirstWindow(); - - if (pWorkspace->m_isSpecialWorkspace) - pMonitor->setSpecialWorkspace(pWorkspace); - else if (POLDWS->m_isSpecialWorkspace) - POLDWS->m_monitor.lock()->setSpecialWorkspace(nullptr); - - pMonitor->changeWorkspace(pWorkspace); - - Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND); - PWINDOW->warpCursor(); - - return {}; -} - -SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { - PHLWINDOW PWINDOW = nullptr; - - if (args.contains(',')) { - PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1)); - args = args.substr(0, args.find_last_of(',')); - } else { - PWINDOW = Desktop::focusState()->window(); - } - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - const auto& [WORKSPACEID, workspaceName, isAutoID] = getWorkspaceIDNameFromString(args); - if (WORKSPACEID == WORKSPACE_INVALID) { - Log::logger->log(Log::ERR, "Error in moveActiveToWorkspaceSilent, invalid value"); - return {.success = false, .error = "Error in moveActiveToWorkspaceSilent, invalid value"}; - } - - if (WORKSPACEID == PWINDOW->workspaceID()) - return {}; - - g_pHyprRenderer->damageWindow(PWINDOW); - - auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); - const auto OLDMIDDLE = PWINDOW->middle(); - - if (pWorkspace) { - g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); - } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); - g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); - } - - if (PWINDOW == Desktop::focusState()->window()) { - if (const auto PATCOORDS = - g_pCompositor->vectorToWindowUnified(OLDMIDDLE, Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING, PWINDOW); - PATCOORDS) - Desktop::focusState()->fullWindowFocus(PATCOORDS, Desktop::FOCUS_REASON_KEYBIND); - else - g_pInputManager->refocus(); - } - - return {}; -} - -SDispatchResult CKeybindManager::moveFocusTo(std::string args) { - static auto PFULLCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_fullscreen"); - static auto PGROUPCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_groupfirst"); - static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback"); - Math::eDirection dir = Math::fromChar(args[0]); - - if (dir == Math::DIRECTION_DEFAULT) { - Log::logger->log(Log::ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]); - return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])}; - } - - const auto PLASTWINDOW = Desktop::focusState()->window(); - if (!PLASTWINDOW || !PLASTWINDOW->aliveAndVisible()) { - if (*PMONITORFALLBACK) - tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(dir)); - return {}; - } - - const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ? - g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, dir != Math::DIRECTION_DOWN && dir != Math::DIRECTION_RIGHT) : - g_pCompositor->getWindowInDirection(PLASTWINDOW, dir); - - // Prioritize focus change within groups if the window is a part of it. - if (*PGROUPCYCLE && PLASTWINDOW->m_group) { - auto isTheOnlyGroupOnWs = !PWINDOWTOCHANGETO && g_pCompositor->m_monitors.size() == 1; - if (dir == Math::DIRECTION_LEFT && (PLASTWINDOW != PLASTWINDOW->m_group->head() || isTheOnlyGroupOnWs)) { - PLASTWINDOW->m_group->moveCurrent(false); - return {}; - } - - else if (dir == Math::DIRECTION_RIGHT && (PLASTWINDOW != PLASTWINDOW->m_group->tail() || isTheOnlyGroupOnWs)) { - PLASTWINDOW->m_group->moveCurrent(true); - return {}; - } - } - - // Found window in direction, switch to it - if (PWINDOWTOCHANGETO) { - switchToWindow(PWINDOWTOCHANGETO, *PFULLCYCLE && PLASTWINDOW->isFullscreen()); - return {}; - } - - Log::logger->log(Log::DEBUG, "No window found in direction {}, looking for a monitor", Math::toString(dir)); - - if (*PMONITORFALLBACK && tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(dir))) - return {}; - - static auto PNOFALLBACK = CConfigValue<Hyprlang::INT>("general:no_focus_fallback"); - if (*PNOFALLBACK) - return {.success = false, .error = std::format("Nothing to focus to in direction {}", Math::toString(dir))}; - - Log::logger->log(Log::DEBUG, "No monitor found in direction {}, getting the inverse edge", Math::toString(dir)); - - const auto PMONITOR = PLASTWINDOW->m_monitor.lock(); - - if (!PMONITOR) - return {.success = false, .error = "last window has no monitor?"}; - - if (dir == Math::DIRECTION_LEFT || dir == Math::DIRECTION_RIGHT) { - if (STICKS(PLASTWINDOW->m_position.x, PMONITOR->m_position.x) && STICKS(PLASTWINDOW->m_size.x, PMONITOR->m_size.x)) - return {.success = false, .error = "move does not make sense, would return back"}; - } else if (STICKS(PLASTWINDOW->m_position.y, PMONITOR->m_position.y) && STICKS(PLASTWINDOW->m_size.y, PMONITOR->m_size.y)) - return {.success = false, .error = "move does not make sense, would return back"}; - - CBox box = PMONITOR->logicalBox(); - switch (dir) { - case Math::DIRECTION_LEFT: - box.x += box.w; - box.w = 1; - break; - case Math::DIRECTION_RIGHT: - box.x -= 1; - box.w = 1; - break; - case Math::DIRECTION_UP: - box.y += box.h; - box.h = 1; - break; - case Math::DIRECTION_DOWN: - box.y -= 1; - box.h = 1; - break; - default: break; - } - - const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->m_activeSpecialWorkspace ? PMONITOR->m_activeSpecialWorkspace : PMONITOR->m_activeWorkspace, - dir, PLASTWINDOW, PLASTWINDOW->m_isFloating); - if (PWINDOWCANDIDATE) - switchToWindow(PWINDOWCANDIDATE); - - return {}; -} - -SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) { - const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); - const auto PWINDOWURGENT = g_pCompositor->getUrgentWindow(); - const auto PWINDOWPREV = Desktop::focusState()->window() ? (HISTORY.size() < 2 ? nullptr : HISTORY[1].lock()) : (HISTORY.empty() ? nullptr : HISTORY[0].lock()); - - if (!PWINDOWURGENT && !PWINDOWPREV) - return {.success = false, .error = "Window not found"}; - - switchToWindow(PWINDOWURGENT ? PWINDOWURGENT : PWINDOWPREV); - - return {}; -} - -SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) { - const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); - - if (HISTORY.size() <= 1) - return {.success = false, .error = "History too short"}; - - const auto PWINDOWPREV = HISTORY[HISTORY.size() - 2].lock(); - - if (!PWINDOWPREV) - return {.success = false, .error = "Window not found"}; - - switchToWindow(PWINDOWPREV); - - return {}; -} - -SDispatchResult CKeybindManager::swapActive(std::string args) { - const auto PLASTWINDOW = Desktop::focusState()->window(); - PHLWINDOW PWINDOWTOCHANGETO = nullptr; - - if (!PLASTWINDOW) - return {.success = false, .error = "Window to swap with not found"}; - - if (PLASTWINDOW->isFullscreen()) - return {.success = false, .error = "Can't swap fullscreen window"}; - - if (isDirection(args)) { - Math::eDirection dir = Math::fromChar(args[0]); - PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, dir); - } else - PWINDOWTOCHANGETO = g_pCompositor->getWindowByRegex(args); - - if (!PWINDOWTOCHANGETO || PWINDOWTOCHANGETO == PLASTWINDOW) { - Log::logger->log(Log::ERR, "Can't swap with {}, invalid window", args); - return {.success = false, .error = std::format("Can't swap with {}, invalid window", args)}; - } - - Log::logger->log(Log::DEBUG, "Swapping active window with {}", args); - - updateRelativeCursorCoords(); - g_layoutManager->switchTargets(PLASTWINDOW->layoutTarget(), PWINDOWTOCHANGETO->layoutTarget(), true); - PLASTWINDOW->warpCursor(); - return {}; -} - -SDispatchResult CKeybindManager::moveActiveTo(std::string args) { - bool silent = args.ends_with(" silent"); - if (silent) - args = args.substr(0, args.length() - 7); - - if (args.starts_with("mon:")) { - const auto PNEWMONITOR = g_pCompositor->getMonitorFromString(args.substr(4)); - if (!PNEWMONITOR) - return {.success = false, .error = std::format("Monitor {} not found", args.substr(4))}; - - if (silent) - moveActiveToWorkspaceSilent(PNEWMONITOR->m_activeWorkspace->getConfigName()); - else - moveActiveToWorkspace(PNEWMONITOR->m_activeWorkspace->getConfigName()); - - return {}; - } - - Math::eDirection dir = Math::fromChar(args[0]); - if (dir == Math::DIRECTION_DEFAULT) { - Log::logger->log(Log::ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]); - return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])}; - } - - const auto PLASTWINDOW = Desktop::focusState()->window(); - - if (!PLASTWINDOW) - return {.success = false, .error = "Window to move not found"}; - - if (PLASTWINDOW->isFullscreen()) - return {.success = false, .error = "Can't move fullscreen window"}; - - updateRelativeCursorCoords(); - - g_layoutManager->moveInDirection(PLASTWINDOW->layoutTarget(), args, silent); - if (!silent) - PLASTWINDOW->warpCursor(); - - return {}; -} - -SDispatchResult CKeybindManager::toggleGroup(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - if (PWINDOW->isFullscreen()) - g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); - - if (!PWINDOW->m_group) - PWINDOW->m_group = Desktop::View::CGroup::create({PWINDOW}); - else - PWINDOW->m_group->destroy(); - - return {}; -} - -SDispatchResult CKeybindManager::changeGroupActive(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - if (!PWINDOW->m_group) - return {.success = false, .error = "No group"}; - - if (PWINDOW->m_group->size() == 1) - return {.success = false, .error = "Only one window in group"}; - - if (isNumber(args, false)) { - // index starts from '1'; '0' means last window - try { - const int INDEX = std::stoi(args); - if (INDEX <= 0) - PWINDOW->m_group->setCurrent(PWINDOW->m_group->size() - 1); - else - PWINDOW->m_group->setCurrent(INDEX - 1); - } catch (...) { return {.success = false, .error = "invalid idx"}; } - - return {}; - } - - if (args != "b" && args != "prev") - PWINDOW->m_group->moveCurrent(true); - else - PWINDOW->m_group->moveCurrent(false); - - return {}; -} - -SDispatchResult CKeybindManager::focusMonitor(std::string arg) { - const auto PMONITOR = g_pCompositor->getMonitorFromString(arg); - tryMoveFocusToMonitor(PMONITOR); - - return {}; -} - -SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) { - if (!isNumber(arg)) { - Log::logger->log(Log::ERR, "moveCursorToCorner, arg has to be a number."); - return {.success = false, .error = "moveCursorToCorner, arg has to be a number."}; - } - - const auto CORNER = std::stoi(arg); - - if (CORNER < 0 || CORNER > 3) { - Log::logger->log(Log::ERR, "moveCursorToCorner, corner not 0 - 3."); - return {.success = false, .error = "moveCursorToCorner, corner not 0 - 3."}; - } - - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - switch (CORNER) { - case 0: - // bottom left - g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x, PWINDOW->m_realPosition->value().y + PWINDOW->m_realSize->value().y}, true); - break; - case 1: - // bottom right - g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x + PWINDOW->m_realSize->value().x, PWINDOW->m_realPosition->value().y + PWINDOW->m_realSize->value().y}, - true); - break; - case 2: - // top right - g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x + PWINDOW->m_realSize->value().x, PWINDOW->m_realPosition->value().y}, true); - break; - case 3: - // top left - g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x, PWINDOW->m_realPosition->value().y}, true); - break; - } - - return {}; -} - -SDispatchResult CKeybindManager::moveCursor(std::string args) { - std::string x_str, y_str; - int x, y; - - size_t i = args.find_first_of(' '); - if (i == std::string::npos) { - Log::logger->log(Log::ERR, "moveCursor, takes 2 arguments."); - return {.success = false, .error = "moveCursor, takes 2 arguments"}; - } - - x_str = args.substr(0, i); - y_str = args.substr(i + 1); - - if (!isNumber(x_str)) { - Log::logger->log(Log::ERR, "moveCursor, x argument has to be a number."); - return {.success = false, .error = "moveCursor, x argument has to be a number."}; - } - if (!isNumber(y_str)) { - Log::logger->log(Log::ERR, "moveCursor, y argument has to be a number."); - return {.success = false, .error = "moveCursor, y argument has to be a number."}; - } - - x = std::stoi(x_str); - y = std::stoi(y_str); - - g_pCompositor->warpCursorTo({x, y}, true); - g_pInputManager->simulateMouseMovement(); - - return {}; -} - -SDispatchResult CKeybindManager::workspaceOpt(std::string args) { - return {.success = false, .error = "workspaceopt is deprecated"}; -} - -SDispatchResult CKeybindManager::renameWorkspace(std::string args) { - try { - const auto FIRSTSPACEPOS = args.find_first_of(' '); - if (FIRSTSPACEPOS != std::string::npos) { - int workspace = std::stoi(args.substr(0, FIRSTSPACEPOS)); - std::string name = args.substr(FIRSTSPACEPOS + 1); - if (const auto& PWS = g_pCompositor->getWorkspaceByID(workspace); PWS) - PWS->rename(name); - else - return {.success = false, .error = "No such workspace"}; - } else if (const auto& PWS = g_pCompositor->getWorkspaceByID(std::stoi(args)); PWS) - PWS->rename(""); - else - return {.success = false, .error = "No such workspace"}; - } catch (std::exception& e) { - Log::logger->log(Log::ERR, R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what()); - return {.success = false, .error = std::format(R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what())}; - } - - return {}; -} - -SDispatchResult CKeybindManager::exitHyprland(std::string argz) { - Event::bus()->m_events.exit.emit(); - - if (g_pCompositor->m_finalRequests) - return {}; // Exiting deferred until requests complete - - g_pCompositor->stopCompositor(); - return {}; -} - -SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { - PHLMONITOR PMONITOR = g_pCompositor->getMonitorFromString(args); - - if (!PMONITOR) { - Log::logger->log(Log::ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesn't exist"); - return {.success = false, .error = "Ignoring moveCurrentWorkspaceToMonitor: monitor doesn't exist"}; - } - - // get the current workspace - const auto PCURRENTWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; - if (!PCURRENTWORKSPACE) { - Log::logger->log(Log::ERR, "moveCurrentWorkspaceToMonitor invalid workspace!"); - return {.success = false, .error = "moveCurrentWorkspaceToMonitor invalid workspace!"}; - } - - g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR); - - return {}; -} - -SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) { - if (!args.contains(' ')) - return {.success = false, .error = "Invalid arguments, expected: workspace monitor"}; - - std::string workspace = args.substr(0, args.find_first_of(' ')); - std::string monitor = args.substr(args.find_first_of(' ') + 1); - - const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor); - - if (!PMONITOR) { - Log::logger->log(Log::ERR, "Ignoring moveWorkspaceToMonitor: monitor doesn't exist"); - return {.success = false, .error = "Ignoring moveWorkspaceToMonitor: monitor doesn't exist"}; - } - - const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; - - if (WORKSPACEID == WORKSPACE_INVALID) { - Log::logger->log(Log::ERR, "moveWorkspaceToMonitor invalid workspace!"); - return {.success = false, .error = "moveWorkspaceToMonitor invalid workspace!"}; - } - - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); - - if (!PWORKSPACE) { - Log::logger->log(Log::ERR, "moveWorkspaceToMonitor workspace doesn't exist!"); - return {.success = false, .error = "moveWorkspaceToMonitor workspace doesn't exist!"}; - } - - g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); - - return {}; -} - -SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { - auto [workspaceID, workspaceName, isAutoID] = getWorkspaceIDNameFromString(args); - if (workspaceID == WORKSPACE_INVALID) { - Log::logger->log(Log::ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); - return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; - } - - const auto PCURRMONITOR = Desktop::focusState()->monitor(); - - if (!PCURRMONITOR) { - Log::logger->log(Log::ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"); - return {.success = false, .error = "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"}; - } - - auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID); - - if (!pWorkspace) { - pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->m_id, workspaceName); - // we can skip the moving, since it's already on the current monitor - changeworkspace(pWorkspace->getConfigName()); - return {}; - } - - static auto PBACKANDFORTH = CConfigValue<Hyprlang::INT>("binds:workspace_back_and_forth"); - const auto PREVWS = Desktop::History::workspaceTracker()->previousWorkspaceIDName(pWorkspace); - - if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) { - // Workspace to focus is previous workspace - pWorkspace = g_pCompositor->getWorkspaceByID(PREVWS.id); - if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(PREVWS.id, PCURRMONITOR->m_id, PREVWS.name); - - workspaceID = pWorkspace->m_id; - } - - if (pWorkspace->m_monitor != PCURRMONITOR) { - const auto POLDMONITOR = pWorkspace->m_monitor.lock(); - if (!POLDMONITOR) { // wat - Log::logger->log(Log::ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"); - return {.success = false, .error = "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"}; - } - if (POLDMONITOR->activeWorkspaceID() == workspaceID) { - g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR); - return {}; - } else { - g_pCompositor->moveWorkspaceToMonitor(pWorkspace, PCURRMONITOR, true); - } - } - - changeworkspace(pWorkspace->getConfigName()); - - return {}; -} - -SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) { - const auto& [workspaceID, workspaceName, isAutoID] = getWorkspaceIDNameFromString("special:" + args); - if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { - Log::logger->log(Log::ERR, "Invalid workspace passed to special"); - return {.success = false, .error = "Invalid workspace passed to special"}; - } - - bool requestedWorkspaceIsAlreadyOpen = false; - const auto PMONITOR = Desktop::focusState()->monitor(); - auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); - - for (auto const& m : g_pCompositor->m_monitors) { - if (m->activeSpecialWorkspaceID() == workspaceID) { - requestedWorkspaceIsAlreadyOpen = true; - break; - } - } - - updateRelativeCursorCoords(); - - PHLWORKSPACEREF focusedWorkspace; - - if (requestedWorkspaceIsAlreadyOpen && specialOpenOnMonitor == workspaceID) { - // already open on this monitor - Log::logger->log(Log::DEBUG, "Toggling special workspace {} to closed", workspaceID); - PMONITOR->setSpecialWorkspace(nullptr); - - focusedWorkspace = PMONITOR->m_activeWorkspace; - } else { - Log::logger->log(Log::DEBUG, "Toggling special workspace {} to open", workspaceID); - auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID); - - if (!PSPECIALWORKSPACE) - PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->m_id, workspaceName); - - PMONITOR->setSpecialWorkspace(PSPECIALWORKSPACE); - - focusedWorkspace = PSPECIALWORKSPACE; - } - - const static auto PWARPONTOGGLESPECIAL = CConfigValue<Hyprlang::INT>("cursor:warp_on_toggle_special"); - - if (*PWARPONTOGGLESPECIAL > 0) { - auto PLAST = focusedWorkspace->getLastFocusedWindow(); - auto HLSurface = Desktop::View::CWLSurface::fromResource(g_pSeatManager->m_state.pointerFocus.lock()); - - if (PLAST && (!HLSurface || HLSurface->view()->type() == Desktop::View::VIEW_TYPE_WINDOW)) - PLAST->warpCursor(*PWARPONTOGGLESPECIAL == 2); - } - - return {}; -} - -SDispatchResult CKeybindManager::forceRendererReload(std::string args) { - bool overAgain = false; - - for (auto const& m : g_pCompositor->m_monitors) { - if (!m->m_output) - continue; - - auto rule = Config::monitorRuleMgr()->get(m); - if (!m->applyMonitorRule(std::move(rule), true)) { - overAgain = true; - break; - } - } - - if (overAgain) - forceRendererReload(args); - - return {}; -} - -SDispatchResult CKeybindManager::resizeActive(std::string args) { - const auto PLASTWINDOW = Desktop::focusState()->window(); - - if (!PLASTWINDOW) - return {.success = false, .error = "No window found"}; - - if (PLASTWINDOW->isFullscreen()) - return {.success = false, .error = "Window is fullscreen"}; - - const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_realSize->goal()); - - if (SIZ.x < 1 || SIZ.y < 1) - return {.success = false, .error = "Invalid size provided"}; - - g_layoutManager->resizeTarget(SIZ - PLASTWINDOW->m_realSize->goal(), PLASTWINDOW->layoutTarget()); - - if (PLASTWINDOW->m_realSize->goal().x > 1 && PLASTWINDOW->m_realSize->goal().y > 1) - PLASTWINDOW->setHidden(false); - - return {}; -} - -SDispatchResult CKeybindManager::moveActive(std::string args) { - const auto PLASTWINDOW = Desktop::focusState()->window(); - - if (!PLASTWINDOW) - return {.success = false, .error = "No window found"}; - - if (PLASTWINDOW->isFullscreen()) - return {.success = false, .error = "Window is fullscreen"}; - - const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_realPosition->goal()); - - g_layoutManager->moveTarget(POS - PLASTWINDOW->m_realPosition->goal(), PLASTWINDOW->layoutTarget()); - - return {}; -} - -SDispatchResult CKeybindManager::moveWindow(std::string args) { - - const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1); - const auto MOVECMD = args.substr(0, args.find_first_of(',')); - - const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "moveWindow: no window"); - return {.success = false, .error = "moveWindow: no window"}; - } - - if (PWINDOW->isFullscreen()) - return {.success = false, .error = "Window is fullscreen"}; - - const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_realPosition->goal()); - - g_layoutManager->moveTarget(POS - PWINDOW->m_realPosition->goal(), PWINDOW->layoutTarget()); - - return {}; -} - -SDispatchResult CKeybindManager::resizeWindow(std::string args) { - - const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1); - const auto MOVECMD = args.substr(0, args.find_first_of(',')); - - const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "resizeWindow: no window"); - return {.success = false, .error = "resizeWindow: no window"}; - } - - if (PWINDOW->isFullscreen()) - return {.success = false, .error = "Window is fullscreen"}; - - const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_realSize->goal()); - - if (SIZ.x < 1 || SIZ.y < 1) - return {.success = false, .error = "Invalid size provided"}; - - g_layoutManager->resizeTarget(SIZ - PWINDOW->m_realSize->goal(), PWINDOW->layoutTarget(), Layout::CORNER_NONE); - - if (PWINDOW->m_realSize->goal().x > 1 && PWINDOW->m_realSize->goal().y > 1) - PWINDOW->setHidden(false); - - return {}; -} - -SDispatchResult CKeybindManager::circleNext(std::string arg) { - if (!Desktop::focusState()->window()) { - // if we have a clear focus, find the first window and get the next focusable. - const auto PWS = Desktop::focusState()->monitor()->m_activeWorkspace; - if (PWS && PWS->getWindows() > 0) { - const auto PWINDOW = PWS->getFirstWindow(); - switchToWindow(PWINDOW); - } - - return {}; - } - - CVarList args{arg, 0, 's', true}; - - const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l"); - - std::optional<bool> floatStatus = {}; - if (args.contains("tile") || args.contains("tiled")) { - // if we want just tiled, and we are on a tiled window, use layoutmsg for layouts that support it - - if (!Desktop::focusState()->window()->m_isFloating) { - if (const auto SPACE = Desktop::focusState()->window()->layoutTarget()->space(); SPACE) { - - constexpr const std::array<const std::type_info*, 2> LAYOUTS_WITH_CYCLE_NEXT = { - &typeid(Layout::Tiled::CMonocleAlgorithm), - &typeid(Layout::Tiled::CMasterAlgorithm), - }; - - if (std::ranges::contains(LAYOUTS_WITH_CYCLE_NEXT, &typeid(*SPACE->algorithm()->tiledAlgo().get()))) { - CKeybindManager::layoutmsg(PREV ? "cyclenext, b" : "cyclenext"); - return {}; - } - } - } - } - - if (args.contains("float") || args.contains("floating")) - floatStatus = true; - - const auto VISIBLE = args.contains("visible") || args.contains("v"); - const auto NEXT = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab - const auto HIST = args.contains("hist") || args.contains("h"); - const auto& w = HIST ? g_pCompositor->getWindowCycleHist(Desktop::focusState()->window(), true, floatStatus, VISIBLE, NEXT) : - g_pCompositor->getWindowCycle(Desktop::focusState()->window(), true, floatStatus, VISIBLE, PREV); - - switchToWindow(w, HIST); - - return {}; -} - -SDispatchResult CKeybindManager::focusWindow(std::string regexp) { - const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp); - - if (!PWINDOW) - return {.success = false, .error = "No such window found"}; - - Log::logger->log(Log::DEBUG, "Focusing to window name: {}", PWINDOW->m_title); - - const auto PWORKSPACE = PWINDOW->m_workspace; - if (!PWORKSPACE) { - Log::logger->log(Log::ERR, "BUG THIS: null workspace in focusWindow"); - return {.success = false, .error = "BUG THIS: null workspace in focusWindow"}; - } - - updateRelativeCursorCoords(); - - if (Desktop::focusState()->monitor() && Desktop::focusState()->monitor()->m_activeWorkspace != PWINDOW->m_workspace && - Desktop::focusState()->monitor()->m_activeSpecialWorkspace != PWINDOW->m_workspace) { - Log::logger->log(Log::DEBUG, "Fake executing workspace to move focus"); - changeworkspace(PWORKSPACE->getConfigName()); - } - - Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND, nullptr, false); - - PWINDOW->warpCursor(); - - return {}; -} - -SDispatchResult CKeybindManager::tagWindow(std::string args) { - PHLWINDOW PWINDOW = nullptr; - CVarList vars{args, 0, 's', true}; - - if (vars.size() == 1) - PWINDOW = Desktop::focusState()->window(); - else if (vars.size() == 2) - PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); - else - return {.success = false, .error = "Invalid number of arguments, expected 1 or 2 arguments"}; - - if (PWINDOW && PWINDOW->m_ruleApplicator->m_tagKeeper.applyTag(vars[0])) { - PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_TAG); - PWINDOW->updateDecorationValues(); - } - - return {}; -} - -SDispatchResult CKeybindManager::toggleSwallow(std::string args) { - PHLWINDOWREF pWindow = Desktop::focusState()->window(); - - if (!valid(pWindow) || !valid(pWindow->m_swallowed)) - return {}; - - if (pWindow->m_swallowed->m_currentlySwallowed) { - // Unswallow - pWindow->m_swallowed->m_currentlySwallowed = false; - pWindow->m_swallowed->setHidden(false); - g_layoutManager->newTarget(pWindow->m_swallowed->layoutTarget(), pWindow->m_workspace->m_space); - } else { - // Reswallow - pWindow->m_swallowed->m_currentlySwallowed = true; - pWindow->m_swallowed->setHidden(true); - g_layoutManager->removeTarget(pWindow->m_swallowed->layoutTarget()); - } - - return {}; -} - -SDispatchResult CKeybindManager::setSubmap(std::string submap) { - if (submap == "reset" || submap.empty()) { - m_currentSelectedSubmap.name = ""; - Log::logger->log(Log::DEBUG, "Reset active submap to the default one."); - g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""}); - Event::bus()->m_events.keybinds.submap.emit(m_currentSelectedSubmap.name); - return {}; - } - - for (const auto& k : g_pKeybindManager->m_keybinds) { - if (k->submap.name == submap) { - m_currentSelectedSubmap.name = submap; - Log::logger->log(Log::DEBUG, "Changed keybind submap to {}", submap); - g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap}); - Event::bus()->m_events.keybinds.submap.emit(m_currentSelectedSubmap.name); - return {}; - } - } - - Log::logger->log(Log::ERR, "Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap); - return {.success = false, .error = std::format("Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap)}; -} - -SDispatchResult CKeybindManager::pass(std::string regexp) { - - // find the first window passing the regex - const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "pass: window not found"); - return {.success = false, .error = "pass: window not found"}; - } - - if (!g_pSeatManager->m_keyboard) { - Log::logger->log(Log::ERR, "No kb in pass?"); - return {.success = false, .error = "No kb in pass?"}; - } - - const auto XWTOXW = PWINDOW->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11; - const auto LASTMOUSESURF = g_pSeatManager->m_state.pointerFocus.lock(); - const auto LASTKBSURF = g_pSeatManager->m_state.keyboardFocus.lock(); - - // pass all mf shit - if (!XWTOXW) { - if (g_pKeybindManager->m_lastCode != 0) - g_pSeatManager->setKeyboardFocus(PWINDOW->wlSurface()->resource()); - else - g_pSeatManager->setPointerFocus(PWINDOW->wlSurface()->resource(), {1, 1}); - } - - g_pSeatManager->sendKeyboardMods(g_pInputManager->getModsFromAllKBs(), 0, 0, 0); - - if (g_pKeybindManager->m_passPressed == 1) { - if (g_pKeybindManager->m_lastCode != 0) - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); - else - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); - } else if (g_pKeybindManager->m_passPressed == 0) - if (g_pKeybindManager->m_lastCode != 0) - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); - else - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); - else { - // dynamic call of the dispatcher - if (g_pKeybindManager->m_lastCode != 0) { - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); - } else { - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); - } - } - - if (XWTOXW) - return {}; - - // Massive hack: - // this will make g_pSeatManager NOT send the leave event to XWayland apps, provided we are not on an XWayland window already. - // please kill me - if (PWINDOW->m_isX11) { - if (g_pKeybindManager->m_lastCode != 0) { - g_pSeatManager->m_state.keyboardFocus.reset(); - g_pSeatManager->m_state.keyboardFocusResource.reset(); - } else { - g_pSeatManager->m_state.pointerFocus.reset(); - g_pSeatManager->m_state.pointerFocusResource.reset(); - } - } - - const auto SL = PWINDOW->m_realPosition->goal() - g_pInputManager->getMouseCoordsInternal(); - - if (g_pKeybindManager->m_lastCode != 0) - g_pSeatManager->setKeyboardFocus(LASTKBSURF); - else - g_pSeatManager->setPointerFocus(LASTMOUSESURF, SL); - - return {}; -} - -SDispatchResult CKeybindManager::sendshortcut(std::string args) { - // args=<NEW_MODKEYS><NEW_KEY>[,WINDOW_RULES] - const auto ARGS = CVarList(args, 3); - if (ARGS.size() != 3) { - Log::logger->log(Log::ERR, "sendshortcut: invalid args"); - return {.success = false, .error = "sendshortcut: invalid args"}; - } - - const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]); - const auto KEY = ARGS[1]; - uint32_t keycode = 0; - bool isMouse = false; - - // 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 = true; - if (keycode < 272) { - Log::logger->log(Log::ERR, "sendshortcut: invalid mouse button"); - return {.success = false, .error = "sendshortcut: invalid mouse button"}; - } - } 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->m_keyboard; - - if (!KB) { - Log::logger->log(Log::ERR, "sendshortcut: no kb"); - return {.success = false, .error = "sendshortcut: no kb"}; - } - - const auto KEYPAIRSTRING = std::format("{}{}", rc<uintptr_t>(KB.get()), KEY); - - if (!g_pKeybindManager->m_keyToCodeCache.contains(KEYPAIRSTRING)) { - xkb_keymap* km = KB->m_xkbKeymap; - xkb_state* ks = KB->m_xkbState; - - 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_keyToCodeCache[KEYPAIRSTRING] = keycode; - } - } - - if (!keycode) { - Log::logger->log(Log::ERR, "sendshortcut: key not found"); - return {.success = false, .error = "sendshortcut: key not found"}; - } - - } else - keycode = g_pKeybindManager->m_keyToCodeCache[KEYPAIRSTRING]; - } - - if (!keycode) { - Log::logger->log(Log::ERR, "sendshortcut: invalid key"); - return {.success = false, .error = "sendshortcut: invalid key"}; - } - - const std::string regexp = ARGS[2]; - PHLWINDOW PWINDOW = nullptr; - const auto LASTSURFACE = Desktop::focusState()->surface(); - - //if regexp is not empty, send shortcut to current window - //else, don't change focus - if (!regexp.empty()) { - PWINDOW = g_pCompositor->getWindowByRegex(regexp); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "sendshortcut: window not found"); - return {.success = false, .error = "sendshortcut: window not found"}; - } - - if (!g_pSeatManager->m_keyboard) { - Log::logger->log(Log::ERR, "No kb in sendshortcut?"); - return {.success = false, .error = "No kb in sendshortcut?"}; - } - - if (!isMouse) - g_pSeatManager->setKeyboardFocus(PWINDOW->wlSurface()->resource()); - else - g_pSeatManager->setPointerFocus(PWINDOW->wlSurface()->resource(), {1, 1}); - } - - //copied the rest from pass and modified it - // if wl -> xwl, activate destination - if (PWINDOW && PWINDOW->m_isX11 && Desktop::focusState()->window() && !Desktop::focusState()->window()->m_isX11) - g_pXWaylandManager->activateSurface(PWINDOW->wlSurface()->resource(), true); - // if xwl -> xwl, send to current. Timing issues make this not work. - if (PWINDOW && PWINDOW->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11) - PWINDOW = nullptr; - - g_pSeatManager->sendKeyboardMods(MOD, 0, 0, 0); - - if (g_pKeybindManager->m_passPressed == 1) { - if (!isMouse) - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); - else - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED); - } else if (g_pKeybindManager->m_passPressed == 0) { - if (!isMouse) - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); - else - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED); - } else { - // dynamic call of the dispatcher - if (!isMouse) { - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); - g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); - } else { - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED); - g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED); - } - } - - g_pSeatManager->sendKeyboardMods(0, 0, 0, 0); - - if (!PWINDOW) - return {}; - - if (PWINDOW->m_isX11) { //xwayland hack, see pass - if (!isMouse) { - g_pSeatManager->m_state.keyboardFocus.reset(); - g_pSeatManager->m_state.keyboardFocusResource.reset(); - } else { - g_pSeatManager->m_state.pointerFocus.reset(); - g_pSeatManager->m_state.pointerFocusResource.reset(); - } - } - - const auto SL = PWINDOW->m_realPosition->goal() - g_pInputManager->getMouseCoordsInternal(); - - if (!isMouse) - g_pSeatManager->setKeyboardFocus(LASTSURFACE); - else - g_pSeatManager->setPointerFocus(LASTSURFACE, SL); - - return {}; -} - -SDispatchResult CKeybindManager::layoutmsg(std::string msg) { - auto ret = g_layoutManager->layoutMsg(msg); - if (!ret) - return {.success = false, .error = ret.error()}; - return {}; -} - -SDispatchResult CKeybindManager::dpms(std::string arg) { - SDispatchResult res; - bool enable = arg.starts_with("on"); - std::string port = ""; - - bool isToggle = arg.starts_with("toggle"); - if (arg.find_first_of(' ') != std::string::npos) - port = arg.substr(arg.find_first_of(' ') + 1); - - for (auto const& m : g_pCompositor->m_realMonitors) { - if (!m->m_enabled) - continue; - - if (!port.empty() && m->m_name != port) - continue; - - if (isToggle) - enable = !m->m_dpmsStatus; - - m->setDPMS(enable); - } - - g_pCompositor->m_dpmsStateOn = enable; - - g_pPointerManager->recheckEnteredOutputs(); - - return res; -} - -SDispatchResult CKeybindManager::swapnext(std::string arg) { - - PHLWINDOW toSwap = nullptr; - - if (!Desktop::focusState()->window()) - return {}; - - const auto PLASTWINDOW = Desktop::focusState()->window(); - - const auto PLASTCYCLED = - validMapped(Desktop::focusState()->window()->m_lastCycledWindow) && Desktop::focusState()->window()->m_lastCycledWindow->m_workspace == PLASTWINDOW->m_workspace ? - Desktop::focusState()->window()->m_lastCycledWindow.lock() : - nullptr; - - const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p"; - toSwap = g_pCompositor->getWindowCycle(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true, std::nullopt, false, NEED_PREV); - - // sometimes we may come back to ourselves. - if (toSwap == PLASTWINDOW) - toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV); - - g_layoutManager->switchTargets(PLASTWINDOW->layoutTarget(), toSwap->layoutTarget(), false); - - PLASTWINDOW->m_lastCycledWindow = toSwap; - - Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_KEYBIND); - - return {}; -} - -SDispatchResult CKeybindManager::swapActiveWorkspaces(std::string args) { - const auto MON1 = args.substr(0, args.find_first_of(' ')); - const auto MON2 = args.substr(args.find_first_of(' ') + 1); - - const auto PMON1 = g_pCompositor->getMonitorFromString(MON1); - const auto PMON2 = g_pCompositor->getMonitorFromString(MON2); - - if (!PMON1 || !PMON2) - return {.success = false, .error = "No such monitor found"}; - - if (PMON1 == PMON2) - return {}; - - g_pCompositor->swapActiveWorkspaces(PMON1, PMON2); - - return {}; -} - -SDispatchResult CKeybindManager::pinActive(std::string args) { - - PHLWINDOW PWINDOW = nullptr; - - if (args != "active" && args.length() > 1) - PWINDOW = g_pCompositor->getWindowByRegex(args); - else - PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "pin: window not found"); - return {.success = false, .error = "pin: window not found"}; - } - - if (!PWINDOW->m_isFloating || PWINDOW->isFullscreen()) - return {.success = false, .error = "Window does not qualify to be pinned"}; - - PWINDOW->m_pinned = !PWINDOW->m_pinned; - - const auto PMONITOR = PWINDOW->m_monitor.lock(); - - if (!PMONITOR) { - Log::logger->log(Log::ERR, "pin: monitor not found"); - return {.success = false, .error = "pin: window not found"}; - } - - PWINDOW->layoutTarget()->assignToSpace(PMONITOR->m_activeWorkspace->m_space); - - PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_PINNED); - - const auto PWORKSPACE = PWINDOW->m_workspace; - - PWORKSPACE->m_lastFocusedWindow = - g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS); - - g_pEventManager->postEvent(SHyprIPCEvent{"pin", std::format("{:x},{}", rc<uintptr_t>(PWINDOW.get()), sc<int>(PWINDOW->m_pinned))}); - Event::bus()->m_events.window.pin.emit(PWINDOW); - - g_pHyprRenderer->damageWindow(PWINDOW, true); - - return {}; -} - -SDispatchResult CKeybindManager::mouse(std::string args) { - const auto ARGS = CVarList(args.substr(1), 2, ' '); - const auto PRESSED = args[0] == '1'; - - if (!PRESSED) { - return changeMouseBindMode(MBIND_INVALID); - } - - if (ARGS[0] == "movewindow") { - return changeMouseBindMode(MBIND_MOVE); - } else { - try { - switch (std::stoi(ARGS[1])) { - case 1: return changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break; - case 2: return changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break; - default: return changeMouseBindMode(MBIND_RESIZE); - } - } catch (std::exception& e) { return changeMouseBindMode(MBIND_RESIZE); } - } -} - SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) { if (MODE != MBIND_INVALID) { if (g_layoutManager->dragController()->target()) @@ -2545,601 +841,3 @@ SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) return {}; } - -SDispatchResult CKeybindManager::bringActiveToTop(std::string args) { - if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating) - g_pCompositor->changeWindowZOrder(Desktop::focusState()->window(), true); - - g_pInputManager->simulateMouseMovement(); - - return {}; -} - -SDispatchResult CKeybindManager::alterZOrder(std::string args) { - const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1); - const auto POSITION = args.substr(0, args.find_first_of(',')); - auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); - - if (!PWINDOW && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating) - PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) { - Log::logger->log(Log::ERR, "alterZOrder: no window"); - return {.success = false, .error = "alterZOrder: no window"}; - } - - if (POSITION == "top") - g_pCompositor->changeWindowZOrder(PWINDOW, true); - else if (POSITION == "bottom") - g_pCompositor->changeWindowZOrder(PWINDOW, false); - else { - Log::logger->log(Log::ERR, "alterZOrder: bad position: {}", POSITION); - return {.success = false, .error = "alterZOrder: bad position: {}"}; - } - - g_pInputManager->simulateMouseMovement(); - - return {}; -} - -SDispatchResult CKeybindManager::lockGroups(std::string args) { - if (args == "lock" || args.empty() || args == "lockgroups") - g_pKeybindManager->m_groupsLocked = true; - else if (args == "toggle") - g_pKeybindManager->m_groupsLocked = !g_pKeybindManager->m_groupsLocked; - else - g_pKeybindManager->m_groupsLocked = false; - - g_pEventManager->postEvent(SHyprIPCEvent{"lockgroups", g_pKeybindManager->m_groupsLocked ? "1" : "0"}); - g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - - return {}; -} - -SDispatchResult CKeybindManager::lockActiveGroup(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "No window found"}; - - if (!PWINDOW->m_group) - return {.success = false, .error = "Not a group"}; - - if (args == "lock") - PWINDOW->m_group->setLocked(true); - else if (args == "toggle") - PWINDOW->m_group->setLocked(!PWINDOW->m_group->locked()); - else - PWINDOW->m_group->setLocked(false); - - PWINDOW->updateDecorationValues(); - - return {}; -} - -void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection) { - if (!pWindowInDirection->m_group || pWindowInDirection->m_group->denied()) - return; - - updateRelativeCursorCoords(); - - if (pWindow->m_monitor != pWindowInDirection->m_monitor) { - pWindow->moveToWorkspace(pWindowInDirection->m_workspace); - pWindow->m_monitor = pWindowInDirection->m_monitor; - } - - if (pWindow->m_group) - pWindow->m_group->remove(pWindow); - pWindowInDirection->m_group->add(pWindow); - - pWindowInDirection->m_group->setCurrent(pWindow); - pWindow->updateWindowDecos(); - Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND); - pWindow->warpCursor(); - - g_pEventManager->postEvent(SHyprIPCEvent{"moveintogroup", std::format("{:x}", rc<uintptr_t>(pWindow.get()))}); -} - -void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir) { - static auto BFOCUSREMOVEDWINDOW = CConfigValue<Hyprlang::INT>("group:focus_removed_window"); - - if (!pWindow->m_group) - return; - - WP<Desktop::View::CGroup> group = pWindow->m_group; - - const auto direction = !dir.empty() ? Math::fromChar(dir[0]) : Math::DIRECTION_DEFAULT; - - pWindow->m_group->remove(pWindow, direction); - - if (*BFOCUSREMOVEDWINDOW || !group) { - Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND); - pWindow->warpCursor(); - } else { - Desktop::focusState()->fullWindowFocus(group->current(), Desktop::FOCUS_REASON_KEYBIND); - group->current()->warpCursor(); - } - - g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", rc<uintptr_t>(pWindow.get()))}); -} - -SDispatchResult CKeybindManager::moveIntoGroup(std::string args) { - static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock"); - - if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) - return {}; - - Math::eDirection dir = Math::fromChar(args[0]); - if (dir == Math::DIRECTION_DEFAULT) { - Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]); - return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])}; - } - - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {}; - - auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir); - - if (!PWINDOWINDIR || !PWINDOWINDIR->m_group) - return {}; - - const auto GROUP = PWINDOWINDIR->m_group; - - // Do not move window into locked group if binds:ignore_group_lock is false - if (!*PIGNOREGROUPLOCK && (GROUP->locked() || (PWINDOW->m_group && PWINDOW->m_group->locked()))) - return {}; - - moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); - - return {}; -} - -SDispatchResult CKeybindManager::moveIntoOrCreateGroup(std::string args) { - static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock"); - - if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) - return {}; - - Math::eDirection dir = Math::fromChar(args[0]); - if (dir == Math::DIRECTION_DEFAULT) { - Log::logger->log(Log::ERR, "Cannot move into or create group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]); - return {.success = false, .error = std::format("Cannot move into or create group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])}; - } - - const auto PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {}; - - auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir); - - if (!PWINDOWINDIR) - return {}; - - if (!PWINDOWINDIR->m_group) { - if (PWINDOWINDIR->isFullscreen()) - return {}; - - PWINDOWINDIR->m_group = Desktop::View::CGroup::create({PWINDOWINDIR}); - } - - const auto GROUP = PWINDOWINDIR->m_group; - - if (!*PIGNOREGROUPLOCK && (GROUP->locked() || (PWINDOW->m_group && PWINDOW->m_group->locked()))) - return {}; - - moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); - - return {}; -} - -SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) { - static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock"); - - if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) - return {.success = false, .error = "Groups locked"}; - - PHLWINDOW PWINDOW = nullptr; - - if (args != "active" && args.length() > 1) - PWINDOW = g_pCompositor->getWindowByRegex(args); - else - PWINDOW = Desktop::focusState()->window(); - - if (!PWINDOW) - return {.success = false, .error = "No window found"}; - - if (!PWINDOW->m_group) - return {.success = false, .error = "Window not in a group"}; - - moveWindowOutOfGroup(PWINDOW); - - return {}; -} - -SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) { - static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock"); - - Math::eDirection dir = Math::fromChar(args[0]); - if (dir == Math::DIRECTION_DEFAULT) { - Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]); - return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])}; - } - - const auto PWINDOW = Desktop::focusState()->window(); - if (!PWINDOW) - return {.success = false, .error = "No window found"}; - - if (PWINDOW->isFullscreen()) - return {}; - - if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) { - g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args); - return {}; - } - - const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir); - - const bool ISWINDOWGROUP = PWINDOW->m_group; - const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->m_group->locked(); - const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_group->size() == 1; - const bool ISWINDOWGROUPDENIED = ISWINDOWGROUP && PWINDOW->m_group->denied(); - - updateRelativeCursorCoords(); - - // note: PWINDOWINDIR is not null implies !PWINDOW->m_isFloating - if (PWINDOWINDIR && PWINDOWINDIR->m_group) { // target is group - if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->m_group->locked() || ISWINDOWGROUPLOCKED || ISWINDOWGROUPDENIED)) { - g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args); - PWINDOW->warpCursor(); - } else - moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); - } else if (PWINDOWINDIR) { // target is regular window - if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_groupRules & Desktop::View::GROUP_SET_ALWAYS)) { - g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args); - PWINDOW->warpCursor(); - } else - moveWindowOutOfGroup(PWINDOW, args); - } else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window - moveWindowOutOfGroup(PWINDOW, args); - } else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group - g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args); - PWINDOW->warpCursor(); - } - - PWINDOW->updateDecorationValues(); - - return {}; -} - -SDispatchResult CKeybindManager::setIgnoreGroupLock(std::string args) { - // FIXME: this is no longer possible like this. It's redundant anyways. Can be easily scripted / lua'd - // static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock"); - - // if (args == "toggle") - // *PIGNOREGROUPLOCK = !*PIGNOREGROUPLOCK; - // else - // *PIGNOREGROUPLOCK = args == "on"; - - // g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**PIGNOREGROUPLOCK)}); - - return {}; -} - -SDispatchResult CKeybindManager::denyWindowFromGroup(std::string args) { - const auto PWINDOW = Desktop::focusState()->window(); - if (!PWINDOW || (PWINDOW && PWINDOW->m_group)) - return {}; - - if (args == "toggle") - PWINDOW->m_group->setDenied(!PWINDOW->m_group->denied()); - else - PWINDOW->m_group->setDenied(args == "on"); - - PWINDOW->updateDecorationValues(); - - return {}; -} - -SDispatchResult CKeybindManager::global(std::string args) { - const auto APPID = args.substr(0, args.find_first_of(':')); - const auto NAME = args.substr(args.find_first_of(':') + 1); - - if (NAME.empty()) - return {}; - - if (!PROTO::globalShortcuts->isTaken(APPID, NAME)) - return {}; - - PROTO::globalShortcuts->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_passPressed); - - return {}; -} - -SDispatchResult CKeybindManager::moveGroupWindow(std::string args) { - const auto BACK = args == "b" || args == "prev"; - - const auto PLASTWINDOW = Desktop::focusState()->window(); - - if (!PLASTWINDOW) - return {.success = false, .error = "No window found"}; - - if (!PLASTWINDOW->m_group) - return {.success = false, .error = "Window not in a group"}; - - const auto GROUP = PLASTWINDOW->m_group; - - if (BACK) - GROUP->swapWithLast(); - else - GROUP->swapWithNext(); - - return {}; -} - -SDispatchResult CKeybindManager::event(std::string args) { - g_pEventManager->postEvent(SHyprIPCEvent{"custom", args}); - return {}; -} - -#include <utility> -#include <type_traits> - -template <typename T> -static void parsePropTrivial(Desktop::Types::COverridableVar<T>& prop, const std::string& s) { - static_assert(std::is_same_v<T, bool> || std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, int> || std::is_same_v<T, Hyprlang::FLOAT> || std::is_same_v<T, std::string>, - "Invalid type passed to parsePropTrivial"); - - if (s == "unset") { - prop.unset(Desktop::Types::PRIORITY_SET_PROP); - return; - } - - try { - if constexpr (std::is_same_v<T, bool>) { - if (s == "toggle") - prop.increment(true, Desktop::Types::PRIORITY_SET_PROP); - else - prop = Desktop::Types::COverridableVar<T>(truthy(s), Desktop::Types::PRIORITY_SET_PROP); - } else if constexpr (std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, int>) { - if (s.starts_with("relative")) { - const auto VAL = std::stoi(s.substr(s.find(' ') + 1)); - prop.increment(VAL, Desktop::Types::PRIORITY_SET_PROP); - } else - prop = Desktop::Types::COverridableVar<T>(std::stoull(s), Desktop::Types::PRIORITY_SET_PROP); - } else if constexpr (std::is_same_v<T, Hyprlang::FLOAT>) { - if (s.starts_with("relative")) { - const auto VAL = std::stof(s.substr(s.find(' ') + 1)); - prop.increment(VAL, Desktop::Types::PRIORITY_SET_PROP); - } else - prop = Desktop::Types::COverridableVar<T>(std::stof(s), Desktop::Types::PRIORITY_SET_PROP); - } else if constexpr (std::is_same_v<T, std::string>) - prop = Desktop::Types::COverridableVar<T>(s, Desktop::Types::PRIORITY_SET_PROP); - } catch (...) { Log::logger->log(Log::ERR, "Hyprctl: parsePropTrivial: failed to parse setprop for {}", s); } -} - -SDispatchResult CKeybindManager::setProp(std::string args) { - CVarList vars(args, 3, ' '); - - if (vars.size() < 3) - return {.success = false, .error = "Not enough args"}; - - const auto PLASTWINDOW = Desktop::focusState()->window(); - const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[0]); - - if (!PWINDOW) - return {.success = false, .error = "Window not found"}; - - const auto PROP = vars[1]; - const auto VAL = vars[2]; - - bool noFocus = PWINDOW->m_ruleApplicator->noFocus().valueOrDefault(); - - try { - if (PROP == "max_size") { - const auto SIZE = PWINDOW->calculateExpression(VAL); - if (!SIZE) { - Log::logger->log(Log::ERR, "failed to parse {} as an expression", VAL); - throw "failed to parse expression"; - } - PWINDOW->m_ruleApplicator->maxSizeOverride(Desktop::Types::COverridableVar(*SIZE, Desktop::Types::PRIORITY_SET_PROP)); - PWINDOW->clampWindowSize(std::nullopt, PWINDOW->m_ruleApplicator->maxSize().value()); - PWINDOW->setHidden(false); - } else if (PROP == "min_size") { - const auto SIZE = PWINDOW->calculateExpression(VAL); - if (!SIZE) { - Log::logger->log(Log::ERR, "failed to parse {} as an expression", VAL); - throw "failed to parse expression"; - } - PWINDOW->m_ruleApplicator->minSizeOverride(Desktop::Types::COverridableVar(*SIZE, Desktop::Types::PRIORITY_SET_PROP)); - PWINDOW->clampWindowSize(PWINDOW->m_ruleApplicator->minSize().value(), std::nullopt); - PWINDOW->setHidden(false); - } else if (PROP == "active_border_color" || PROP == "inactive_border_color") { - Config::CGradientValueData colorData = {}; - if (vars.size() > 4) { - for (int i = 3; i < sc<int>(vars.size()); ++i) { - const auto TOKEN = vars[i]; - if (TOKEN.ends_with("deg")) - colorData.m_angle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else - configStringToInt(TOKEN).and_then([&colorData](const auto& e) { - colorData.m_colors.push_back(e); - return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1); - }); - } - } else if (VAL != "-1") - configStringToInt(VAL).and_then([&colorData](const auto& e) { - colorData.m_colors.push_back(e); - return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1); - }); - - colorData.updateColorsOk(); - - if (PROP == "active_border_color") - PWINDOW->m_ruleApplicator->activeBorderColorOverride(Desktop::Types::COverridableVar(colorData, Desktop::Types::PRIORITY_SET_PROP)); - else - PWINDOW->m_ruleApplicator->inactiveBorderColorOverride(Desktop::Types::COverridableVar(colorData, Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "opacity") { - PWINDOW->m_ruleApplicator->alphaOverride(Desktop::Types::COverridableVar( - Desktop::Types::SAlphaValue{std::stof(VAL), PWINDOW->m_ruleApplicator->alpha().valueOrDefault().overridden}, Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "opacity_inactive") { - PWINDOW->m_ruleApplicator->alphaInactiveOverride(Desktop::Types::COverridableVar( - Desktop::Types::SAlphaValue{std::stof(VAL), PWINDOW->m_ruleApplicator->alphaInactive().valueOrDefault().overridden}, Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "opacity_fullscreen") { - PWINDOW->m_ruleApplicator->alphaFullscreenOverride(Desktop::Types::COverridableVar( - Desktop::Types::SAlphaValue{std::stof(VAL), PWINDOW->m_ruleApplicator->alphaFullscreen().valueOrDefault().overridden}, Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "opacity_override") { - PWINDOW->m_ruleApplicator->alphaOverride(Desktop::Types::COverridableVar( - Desktop::Types::SAlphaValue{PWINDOW->m_ruleApplicator->alpha().valueOrDefault().alpha, sc<bool>(configStringToInt(VAL).value_or(0))}, - Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "opacity_inactive_override") { - PWINDOW->m_ruleApplicator->alphaInactiveOverride(Desktop::Types::COverridableVar( - Desktop::Types::SAlphaValue{PWINDOW->m_ruleApplicator->alphaInactive().valueOrDefault().alpha, sc<bool>(configStringToInt(VAL).value_or(0))}, - Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "opacity_fullscreen_override") { - PWINDOW->m_ruleApplicator->alphaFullscreenOverride(Desktop::Types::COverridableVar( - Desktop::Types::SAlphaValue{PWINDOW->m_ruleApplicator->alphaFullscreen().valueOrDefault().alpha, sc<bool>(configStringToInt(VAL).value_or(0))}, - Desktop::Types::PRIORITY_SET_PROP)); - } else if (PROP == "allows_input") - parsePropTrivial(PWINDOW->m_ruleApplicator->allowsInput(), VAL); - else if (PROP == "decorate") - parsePropTrivial(PWINDOW->m_ruleApplicator->decorate(), VAL); - else if (PROP == "focus_on_activate") - parsePropTrivial(PWINDOW->m_ruleApplicator->focusOnActivate(), VAL); - else if (PROP == "keep_aspect_ratio") - parsePropTrivial(PWINDOW->m_ruleApplicator->keepAspectRatio(), VAL); - else if (PROP == "nearest_neighbor") - parsePropTrivial(PWINDOW->m_ruleApplicator->nearestNeighbor(), VAL); - else if (PROP == "no_anim") - parsePropTrivial(PWINDOW->m_ruleApplicator->noAnim(), VAL); - else if (PROP == "no_blur") - parsePropTrivial(PWINDOW->m_ruleApplicator->noBlur(), VAL); - else if (PROP == "no_dim") - parsePropTrivial(PWINDOW->m_ruleApplicator->noDim(), VAL); - else if (PROP == "no_focus") - parsePropTrivial(PWINDOW->m_ruleApplicator->noFocus(), VAL); - else if (PROP == "no_max_size") - parsePropTrivial(PWINDOW->m_ruleApplicator->noMaxSize(), VAL); - else if (PROP == "no_shadow") - parsePropTrivial(PWINDOW->m_ruleApplicator->noShadow(), VAL); - else if (PROP == "no_shortcuts_inhibit") - parsePropTrivial(PWINDOW->m_ruleApplicator->noShortcutsInhibit(), VAL); - else if (PROP == "dim_around") - parsePropTrivial(PWINDOW->m_ruleApplicator->dimAround(), VAL); - else if (PROP == "opaque") - parsePropTrivial(PWINDOW->m_ruleApplicator->opaque(), VAL); - else if (PROP == "force_rgbx") - parsePropTrivial(PWINDOW->m_ruleApplicator->RGBX(), VAL); - else if (PROP == "sync_fullscreen") - parsePropTrivial(PWINDOW->m_ruleApplicator->syncFullscreen(), VAL); - else if (PROP == "immediate") - parsePropTrivial(PWINDOW->m_ruleApplicator->tearing(), VAL); - else if (PROP == "xray") - parsePropTrivial(PWINDOW->m_ruleApplicator->xray(), VAL); - else if (PROP == "render_unfocused") - parsePropTrivial(PWINDOW->m_ruleApplicator->renderUnfocused(), VAL); - else if (PROP == "no_follow_mouse") - parsePropTrivial(PWINDOW->m_ruleApplicator->noFollowMouse(), VAL); - else if (PROP == "no_screen_share") - parsePropTrivial(PWINDOW->m_ruleApplicator->noScreenShare(), VAL); - else if (PROP == "no_vrr") - parsePropTrivial(PWINDOW->m_ruleApplicator->noVRR(), VAL); - else if (PROP == "persistent_size") - parsePropTrivial(PWINDOW->m_ruleApplicator->persistentSize(), VAL); - else if (PROP == "stay_focused") - parsePropTrivial(PWINDOW->m_ruleApplicator->stayFocused(), VAL); - else if (PROP == "idle_inhibit") - parsePropTrivial(PWINDOW->m_ruleApplicator->idleInhibitMode(), VAL); - else if (PROP == "border_size") - parsePropTrivial(PWINDOW->m_ruleApplicator->borderSize(), VAL); - else if (PROP == "rounding") - parsePropTrivial(PWINDOW->m_ruleApplicator->rounding(), VAL); - else if (PROP == "rounding_power") - parsePropTrivial(PWINDOW->m_ruleApplicator->roundingPower(), VAL); - else if (PROP == "scroll_mouse") - parsePropTrivial(PWINDOW->m_ruleApplicator->scrollMouse(), VAL); - else if (PROP == "scroll_touchpad") - parsePropTrivial(PWINDOW->m_ruleApplicator->scrollTouchpad(), VAL); - else if (PROP == "animation") - parsePropTrivial(PWINDOW->m_ruleApplicator->animationStyle(), VAL); - else - return {.success = false, .error = "prop not found"}; - - } catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; } - - g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - - if (PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() != noFocus) { - // FIXME: what the fuck is going on here? -vax - Desktop::focusState()->rawWindowFocus(nullptr, Desktop::FOCUS_REASON_KEYBIND); - Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND); - Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_KEYBIND); - } - - if (PROP == "no_vrr") - Config::monitorRuleMgr()->ensureVRR(); - - for (auto const& m : g_pCompositor->m_monitors) { - if (m->m_activeWorkspace) - m->m_activeWorkspace->m_space->recalculate(); - } - - return {}; -} - -SDispatchResult CKeybindManager::forceIdle(std::string args) { - std::optional<float> duration = getPlusMinusKeywordResult(args, 0); - - if (!duration.has_value()) { - Log::logger->log(Log::ERR, "Duration invalid in forceIdle!"); - return {.success = false, .error = "Duration invalid in forceIdle!"}; - } - - PROTO::idle->setTimers(duration.value() * 1000.0); - - return {}; -} - -SDispatchResult CKeybindManager::sendkeystate(std::string args) { - // args=<NEW_MODKEYS><NEW_KEY><STATE>[,WINDOW_RULES] - const auto ARGS = CVarList(args, 4); - if (ARGS.size() != 4) { - Log::logger->log(Log::ERR, "sendkeystate: invalid args"); - return {.success = false, .error = "sendkeystate: invalid args"}; - } - - const auto STATE = ARGS[2]; - - if (STATE != "down" && STATE != "repeat" && STATE != "up") { - Log::logger->log(Log::ERR, "sendkeystate: invalid state, must be 'down', 'repeat', or 'up'"); - return {.success = false, .error = "sendkeystate: invalid state, must be 'down', 'repeat', or 'up'"}; - } - - std::string modifiedArgs = ARGS[0] + "," + ARGS[1] + "," + ARGS[3]; - - const int oldPassPressed = g_pKeybindManager->m_passPressed; - - if (STATE == "down") - g_pKeybindManager->m_passPressed = 1; - else if (STATE == "up") - g_pKeybindManager->m_passPressed = 0; - else if (STATE == "repeat") - g_pKeybindManager->m_passPressed = 1; - - auto result = sendshortcut(modifiedArgs); - - if (STATE == "repeat" && result.success) - result = sendshortcut(modifiedArgs); - - g_pKeybindManager->m_passPressed = oldPassPressed; - - if (!result.success && !result.error.empty()) { - size_t pos = result.error.find("sendshortcut:"); - if (pos != std::string::npos) - result.error = "sendkeystate:" + result.error.substr(pos + 13); - } - - return result; -} |
