From bca3068db224d76b2da3f792efe4d0cb8cd2fe3e Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Fri, 9 Jun 2023 21:44:18 +0000 Subject: [PATCH] feat: add lockactivegroup dispatcher (#2478) * feat: add lockactivegroup dispatcher The `lockactivewindow` dispatcher takes `lock`, `toggle` or `unlock` as arguments. When a group is locked, no window or group can be added to it, nor can it be added to another group, but the `moveintogroup` and `moveoutofgroup` dispatches are not affected. Implementation details: the lock is implement via `SGroupData.locked` flag (defaults to false). The flag is only relevant to the group head, and upon the group head's succession, the flag will be passed down to the new head. Meanwhile, the old head's flag will be set to false. The flag is set to false when a group is dismissed. New condition checks have been added to the dwindle and master layout to check if target group is unlocked (and if the source is also a group and unlocked) before adding windows to the target group. * refactor: `lockactivegroup dispatcher code ordering --- src/Window.cpp | 1 + src/Window.hpp | 1 + src/layout/DwindleLayout.cpp | 4 +++- src/layout/IHyprLayout.cpp | 2 ++ src/layout/MasterLayout.cpp | 4 +++- src/managers/KeybindManager.cpp | 18 ++++++++++++++++++ src/managers/KeybindManager.hpp | 1 + 7 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 7fe83ecce..2b9bb56b5 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -645,6 +645,7 @@ void CWindow::insertWindowToGroup(CWindow* pWindow) { curr = curr->m_sGroupData.pNextWindow; PLAST->m_sGroupData.pNextWindow = nullptr; PLAST->m_sGroupData.head = false; + PLAST->m_sGroupData.locked = false; } while (curr != pWindow); for (auto& w : members) { diff --git a/src/Window.hpp b/src/Window.hpp index c1a36d215..437b4a40b 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -288,6 +288,7 @@ class CWindow { struct SGroupData { CWindow* pNextWindow = nullptr; // nullptr means no grouping. Self means single group. bool head = false; + bool locked = false; } m_sGroupData; // For the list lookup diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 5db9d7710..3d16cb124 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -311,7 +311,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) { } // if it's a group, add the window - if (OPENINGON->pWindow->m_sGroupData.pNextWindow && !g_pKeybindManager->m_bGroupsLocked) { + if (OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked && // target is an unlocked group + (!pWindow->m_sGroupData.pNextWindow || !pWindow->getGroupHead()->m_sGroupData.locked) // source is not group or is a unlocked group + && !g_pKeybindManager->m_bGroupsLocked) { m_lDwindleNodesData.remove(*PNODE); OPENINGON->pWindow->insertWindowToGroup(pWindow); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index b5663b698..8f2566300 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -45,6 +45,8 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) { if (pWindow->m_sGroupData.head) { pWindow->m_sGroupData.head = false; curr->m_sGroupData.head = true; + curr->m_sGroupData.locked = pWindow->m_sGroupData.locked; + pWindow->m_sGroupData.locked = false; } if (pWindow == m_pLastTiledWindow) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8f208fdbb..494fd7a27 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -91,7 +91,9 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) { getNodeFromWindow(g_pCompositor->m_pLastWindow) : getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID); - if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && OPENINGON != PNODE && !g_pKeybindManager->m_bGroupsLocked) { + if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked && // target is an unlocked group + (!pWindow->m_sGroupData.pNextWindow || !pWindow->getGroupHead()->m_sGroupData.locked) // source is not group or is an unlocked group + && OPENINGON != PNODE && !g_pKeybindManager->m_bGroupsLocked) { m_lMasterNodesData.remove(*PNODE); OPENINGON->pWindow->insertWindowToGroup(pWindow); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 34a7defa2..77df730d5 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -63,6 +63,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast; m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast; m_mDispatchers["lockgroups"] = lockGroups; + m_mDispatchers["lockactivegroup"] = lockActiveGroup; m_mDispatchers["moveintogroup"] = moveIntoGroup; m_mDispatchers["moveoutofgroup"] = moveOutOfGroup; m_mDispatchers["global"] = global; @@ -1173,6 +1174,7 @@ void CKeybindManager::toggleGroup(std::string args) { if (!PWINDOW->m_sGroupData.pNextWindow) { PWINDOW->m_sGroupData.pNextWindow = PWINDOW; PWINDOW->m_sGroupData.head = true; + PWINDOW->m_sGroupData.locked = false; PWINDOW->m_dWindowDecorations.emplace_back(std::make_unique(PWINDOW)); @@ -1989,6 +1991,22 @@ void CKeybindManager::lockGroups(std::string args) { } } +void CKeybindManager::lockActiveGroup(std::string args) { + const auto PWINDOW = g_pCompositor->m_pLastWindow; + + if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow) + return; + const auto PHEAD = PWINDOW->getGroupHead(); + + if (args == "lock") { + PHEAD->m_sGroupData.locked = true; + } else if (args == "toggle") { + PHEAD->m_sGroupData.locked = !PHEAD->m_sGroupData.locked; + } else { + PHEAD->m_sGroupData.locked = false; + } +} + void CKeybindManager::moveIntoGroup(std::string args) { char arg = args[0]; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 5b7e6186a..b45e83faf 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -140,6 +140,7 @@ class CKeybindManager { static void mouse(std::string); static void bringActiveToTop(std::string); static void lockGroups(std::string); + static void lockActiveGroup(std::string); static void moveIntoGroup(std::string); static void moveOutOfGroup(std::string); static void global(std::string);