diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b2d9ab57d..3828e9e88 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -791,5 +791,66 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) { } } + return nullptr; +} + +SMonitor* CCompositor::getMonitorInDirection(const char& dir) { + const auto POSA = m_pLastMonitor->vecPosition; + const auto SIZEA = m_pLastMonitor->vecSize; + + auto longestIntersect = -1; + SMonitor* longestIntersectMonitor = nullptr; + + for (auto& m : m_lMonitors) { + if (&m == m_pLastMonitor) + continue; + + const auto POSB = m.vecPosition; + const auto SIZEB = m.vecSize; + switch (dir) { + case 'l': + if (STICKS(POSA.x, POSB.x + SIZEB.x)) { + const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); + if (INTERSECTLEN > longestIntersect) { + longestIntersect = INTERSECTLEN; + longestIntersectMonitor = &m; + } + } + break; + case 'r': + if (STICKS(POSA.x + SIZEA.x, POSB.x)) { + const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); + if (INTERSECTLEN > longestIntersect) { + longestIntersect = INTERSECTLEN; + longestIntersectMonitor = &m; + } + } + break; + case 't': + case 'u': + if (STICKS(POSA.y, POSB.y + SIZEB.y)) { + const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); + if (INTERSECTLEN > longestIntersect) { + longestIntersect = INTERSECTLEN; + longestIntersectMonitor = &m; + } + } + break; + case 'b': + case 'd': + if (STICKS(POSA.y + SIZEA.y, POSB.y)) { + const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); + if (INTERSECTLEN > longestIntersect) { + longestIntersect = INTERSECTLEN; + longestIntersectMonitor = &m; + } + } + break; + } + } + + if (longestIntersect != -1) + return longestIntersectMonitor; + return nullptr; } \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 1a45592c7..bc3b068c5 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -115,6 +115,7 @@ public: int getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); CWindow* getConstraintWindow(SMouse*); + SMonitor* getMonitorInDirection(const char&); private: void initAllSignals(); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 489fa02a8..bf8724c67 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -1,5 +1,6 @@ #include "MiscFunctions.hpp" #include "../defines.hpp" +#include void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) { ASSERT(pSignal); @@ -111,4 +112,12 @@ float getPlusMinusKeywordResult(std::string source, float relative) { } return result; +} + +bool isNumber(const std::string& str) { + return std::ranges::all_of(str.begin(), str.end(), [](char c) { return isdigit(c) != 0; }); +} + +bool isDirection(const std::string& arg) { + return arg == "l" || arg == "r" || arg == "u" || arg == "d" || arg == "t" || arg == "b"; } \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 4fb42e129..e7b207dea 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -7,5 +7,7 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data); std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string void scaleBox(wlr_box*, float); std::string removeBeginEndSpacesTabs(std::string); +bool isNumber(const std::string&); +bool isDirection(const std::string&); float getPlusMinusKeywordResult(std::string in, float relative); \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7e7b4079b..0f4d538aa 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -15,6 +15,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["togglegroup"] = toggleGroup; m_mDispatchers["changegroupactive"] = changeGroupActive; m_mDispatchers["splitratio"] = alterSplitRatio; + m_mDispatchers["focusmonitor"] = focusMonitor; } void CKeybindManager::addKeybind(SKeybind kb) { @@ -328,7 +329,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { void CKeybindManager::moveFocusTo(std::string args) { char arg = args[0]; - if (arg != 'l' && arg != 'r' && arg != 'u' && arg != 'd' && arg != 't' && arg != 'b') { + if (!isDirection(args)) { Debug::log(ERR, "Cannot move focus in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg); return; } @@ -366,7 +367,7 @@ void CKeybindManager::moveFocusTo(std::string args) { void CKeybindManager::moveActiveTo(std::string args) { char arg = args[0]; - if (arg != 'l' && arg != 'r' && arg != 'u' && arg != 'd' && arg != 't' && arg != 'b') { + if (!isDirection(args)) { Debug::log(ERR, "Cannot move window in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg); return; } @@ -415,4 +416,41 @@ void CKeybindManager::alterSplitRatio(std::string args) { return; g_pLayoutManager->getCurrentLayout()->alterSplitRatioBy(PLASTWINDOW, splitratio); +} + +void CKeybindManager::focusMonitor(std::string arg) { + if (isNumber(arg)) { + // change by ID + int monID = -1; + try { + monID = std::stoi(arg); + } catch (std::exception& e) { + // shouldn't happen but jic + Debug::log(ERR, "Error in focusMonitor: invalid num"); + } + + if (monID > -1 && monID < (int)g_pCompositor->m_lMonitors.size()) { + changeworkspace(std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace)); + } else { + Debug::log(ERR, "Error in focusMonitor: invalid arg 1"); + } + } else { + + if (isDirection(arg)) { + const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]); + if (PMONITOR) { + changeworkspace(std::to_string(PMONITOR->activeWorkspace)); + return; + } + } else { + for (auto& m : g_pCompositor->m_lMonitors) { + if (m.szName == arg) { + changeworkspace(std::to_string(m.activeWorkspace)); + return; + } + } + } + + Debug::log(ERR, "Error in focusMonitor: no such monitor"); + } } \ No newline at end of file diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 2561c8adb..9737d0928 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -43,6 +43,7 @@ private: static void toggleGroup(std::string); static void changeGroupActive(std::string); static void alterSplitRatio(std::string); + static void focusMonitor(std::string); }; inline std::unique_ptr g_pKeybindManager; \ No newline at end of file