From 03eac7e26b52edf47d9b9d85aa35b603dc259bd2 Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Fri, 29 Sep 2023 20:04:02 +0200 Subject: [PATCH] Improve ungroupping behavior --- src/main.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ef69869..5001a7b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,9 @@ #include "globals.hpp" +#include #include #include +#include #include #include #include @@ -43,6 +45,16 @@ void moveIntoGroup(CWindow* window, CWindow* groupRootWin) window->setHidden(true); } +void collectGroupWindows(std::deque* pDeque, CWindow* pWindow) +{ + CWindow* curr = pWindow; + do { + const auto PLAST = curr; + pDeque->emplace_back(curr); + curr = curr->m_sGroupData.pNextWindow; + } while (curr != pWindow); +} + void groupDissolve(const SDwindleNodeData* PNODE, CHyprDwindleLayout* layout) { CWindow* PWINDOW = PNODE->pWindow; @@ -54,9 +66,54 @@ void groupDissolve(const SDwindleNodeData* PNODE, CHyprDwindleLayout* layout) return; } + // We could just call originalToggleGroup function here, but that fucntion doesn't + // respect the dwindle layout, and would just place the newly ungroupped windows + // randomly throughout the worskapce, messing up the layout. So instead, we replicate + // it's behavior here manually, taking care to disolve the groups nicely. Debug::log(LOG, "Dissolving group"); - // We currently don't need any special logic for dissolving, just call the original func - originalToggleGroup(""); + + std::deque members; + collectGroupWindows(&members, PWINDOW); + + // If the group head window is in fullscreen, unfullscreen it. + // We need to have the window placed in the layout, to figure out where + // to ungroup the rest of the windows. + g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); + + Debug::log(LOG, "Ungroupping Members"); + + const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; + + for (auto& w : members) { + w->m_sGroupData.pNextWindow = nullptr; + w->setHidden(false); + + // Ask layout to create a new window for all windows that were in the group + // except for the group head (already has a window). + if (w->m_sGroupData.head) { + Debug::log(LOG, "Ungroupping member head window"); + w->m_sGroupData.head = false; + + // Update the window decorations (removing group bar) + // w->updateWindowDecos(); + } + else { + Debug::log(LOG, "Ungroupping member non-head window"); + g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(w); + // Focus the window that we just spawned, so that on the next iteration + // the window created will be it's dwindle child node. + // This allows the original group head to remain a parent window to all + // of the other (groupped) nodes + g_pCompositor->focusWindow(w); + } + } + + g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; + + g_pCompositor->updateAllWindowsAnimatedDecorationValues(); + + // Leave with the focus the original group (head) window + g_pCompositor->focusWindow(PWINDOW); } void groupCreate(const SDwindleNodeData* PNODE, CHyprDwindleLayout* layout)