From 723870337f299d4c80aa0048144f3a1ca1c885bd Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:30:39 +0000 Subject: layout: rethonk layouts from the ground up (#12890) Rewrites layouts to be much smaller, and deal with much less annoying BS. Improves the overall architecture, unifies handling of pseudotiling, and various other improvements. --- src/render/Renderer.cpp | 7 +- src/render/decorations/CHyprGroupBarDecoration.cpp | 122 +++++---------------- src/render/decorations/DecorationPositioner.cpp | 4 +- src/render/pass/SurfacePassElement.cpp | 5 +- 4 files changed, 38 insertions(+), 100 deletions(-) (limited to 'src/render') diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1b95ce8a..b45a2cdc 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -11,7 +11,6 @@ #include "../managers/input/InputManager.hpp" #include "../managers/HookSystemManager.hpp" #include "../managers/animation/AnimationManager.hpp" -#include "../managers/LayoutManager.hpp" #include "../desktop/view/Window.hpp" #include "../desktop/view/LayerSurface.hpp" #include "../desktop/view/GlobalViewMethods.hpp" @@ -28,6 +27,8 @@ #include "../hyprerror/HyprError.hpp" #include "../debug/HyprDebugOverlay.hpp" #include "../debug/HyprNotificationOverlay.hpp" +#include "../layout/LayoutManager.hpp" +#include "../layout/space/Space.hpp" #include "../i18n/Engine.hpp" #include "helpers/CursorShapes.hpp" #include "helpers/Monitor.hpp" @@ -1305,7 +1306,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) { if (pMonitor->m_scheduledRecalc) { pMonitor->m_scheduledRecalc = false; - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->m_id); + pMonitor->m_activeWorkspace->m_space->recalculate(); } if (!pMonitor->m_output->needsFrame && pMonitor->m_forceFullFrames == 0) @@ -1906,7 +1907,7 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { // damage the monitor if can damageMonitor(PMONITOR); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor); + g_layoutManager->invalidateMonitorGeometries(PMONITOR); } void CHyprRenderer::damageSurface(SP pSurface, double x, double y, double scale) { diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 47e39211..beb5efcd 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -2,13 +2,15 @@ #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" #include "../../desktop/state/FocusState.hpp" -#include "managers/LayoutManager.hpp" +#include "../../desktop/view/Group.hpp" #include #include #include "../pass/TexPassElement.hpp" #include "../pass/RectPassElement.hpp" #include "../Renderer.hpp" #include "../../managers/input/InputManager.hpp" +#include "../../layout/LayoutManager.hpp" +#include "../../layout/supplementary/DragController.hpp" // shared things to conserve VRAM static SP m_tGradientActive = makeShared(); @@ -65,19 +67,14 @@ eDecorationType CHyprGroupBarDecoration::getDecorationType() { // void CHyprGroupBarDecoration::updateWindow(PHLWINDOW pWindow) { - if (m_window->m_groupData.pNextWindow.expired()) { + if (!m_window->m_group) { m_window->removeWindowDeco(this); return; } m_dwGroupMembers.clear(); - PHLWINDOW head = pWindow->getGroupHead(); - m_dwGroupMembers.emplace_back(head); - - PHLWINDOW curr = head->m_groupData.pNextWindow.lock(); - while (curr != head) { - m_dwGroupMembers.emplace_back(curr); - curr = curr->m_groupData.pNextWindow.lock(); + for (const auto& w : m_window->m_group->windows()) { + m_dwGroupMembers.emplace_back(w); } damageEntire(); @@ -158,7 +155,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { rect.scale(pMonitor->m_scale).round(); - const bool GROUPLOCKED = m_window->getGroupHead()->m_groupData.locked || g_pKeybindManager->m_groupsLocked; + const bool GROUPLOCKED = m_window->m_group->locked() || g_pKeybindManager->m_groupsLocked; const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; @@ -204,6 +201,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { data.tex = GRADIENTTEX; data.blur = blur; data.box = rect; + data.a = a; if (*PGRADIENTROUNDING) { data.round = *PGRADIENTROUNDING; data.roundingPower = *PGRADIENTROUNDINGPOWER; @@ -391,7 +389,7 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { static auto PSTACKED = CConfigValue("group:groupbar:stacked"); static auto POUTERGAP = CConfigValue("group:groupbar:gaps_out"); static auto PINNERGAP = CConfigValue("group:groupbar:gaps_in"); - if (m_window.lock() == m_window->m_groupData.pNextWindow.lock()) + if (m_window->m_group->size() == 1) return false; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; @@ -404,95 +402,33 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { if (*PSTACKED && (BARRELATIVEY - (m_barHeight + *POUTERGAP) * WINDOWINDEX < *POUTERGAP)) return false; - PHLWINDOW pWindow = m_window->getGroupWindowByIndex(WINDOWINDEX); + PHLWINDOW pWindow = m_window->m_group->fromIndex(WINDOWINDEX); - // hack - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); - if (!pWindow->m_isFloating) { - const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_groupsLocked; - g_pKeybindManager->m_groupsLocked = true; - g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow); - g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV; - } + const auto& GROUP = m_window->m_group; - g_pInputManager->m_currentlyDraggedWindow = pWindow; + // remove the window from the group + GROUP->remove(pWindow); + + // start a move drag on it + g_layoutManager->dragController()->dragBegin(pWindow->layoutTarget(), MBIND_MOVE); if (!g_pCompositor->isWindowActive(pWindow)) - Desktop::focusState()->rawWindowFocus(pWindow); + Desktop::focusState()->rawWindowFocus(pWindow, Desktop::FOCUS_REASON_CLICK); return true; } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); static auto PMERGEGROUPSONGROUPBAR = CConfigValue("group:merge_groups_on_groupbar"); - static auto POUTERGAP = CConfigValue("group:groupbar:gaps_out"); - static auto PINNERGAP = CConfigValue("group:groupbar:gaps_in"); - const bool FLOATEDINTOTILED = !m_window->m_isFloating && !pDraggedWindow->m_draggingTiled; - - g_pInputManager->m_wasDraggingWindow = false; + const bool FLOATEDINTOTILED = !m_window->m_isFloating && !g_layoutManager->dragController()->draggingTiled(); - if (!pDraggedWindow->canBeGroupedInto(m_window.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) || - (!*PMERGEGROUPSONGROUPBAR && pDraggedWindow->m_groupData.pNextWindow.lock() && m_window->m_groupData.pNextWindow.lock())) { - g_pInputManager->m_wasDraggingWindow = true; + if (!pDraggedWindow->canBeGroupedInto(m_window->m_group) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) || + (!*PMERGEGROUPSONGROUPBAR && pDraggedWindow->m_group)) return false; - } - - const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_barHeight + *POUTERGAP) / 2 : pos.x - assignedBoxGlobal().x - m_barWidth / 2; - const float BARSIZE = *PSTACKED ? m_barHeight + *POUTERGAP : m_barWidth + *PINNERGAP; - const int WINDOWINDEX = BARRELATIVE < 0 ? -1 : BARRELATIVE / BARSIZE; - - PHLWINDOW pWindowInsertAfter = m_window->getGroupWindowByIndex(WINDOWINDEX); - PHLWINDOW pWindowInsertEnd = pWindowInsertAfter->m_groupData.pNextWindow.lock(); - PHLWINDOW pDraggedHead = pDraggedWindow->m_groupData.pNextWindow.lock() ? pDraggedWindow->getGroupHead() : pDraggedWindow; - - if (!pDraggedWindow->m_groupData.pNextWindow.expired()) { - - // stores group data - std::vector members; - PHLWINDOW curr = pDraggedHead; - const bool WASLOCKED = pDraggedHead->m_groupData.locked; - do { - members.push_back(curr); - curr = curr->m_groupData.pNextWindow.lock(); - } while (curr != members[0]); - - // removes all windows - for (const PHLWINDOW& w : members) { - w->m_groupData.pNextWindow.reset(); - w->m_groupData.head = false; - w->m_groupData.locked = false; - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(w); - } - - // restores the group - for (auto it = members.begin(); it != members.end(); ++it) { - (*it)->m_isFloating = pWindowInsertAfter->m_isFloating; // match the floating state of group members - *(*it)->m_realSize = pWindowInsertAfter->m_realSize->goal(); // match the size of group members - *(*it)->m_realPosition = pWindowInsertAfter->m_realPosition->goal(); // match the position of group members - if (std::next(it) != members.end()) - (*it)->m_groupData.pNextWindow = *std::next(it); - else - (*it)->m_groupData.pNextWindow = members[0]; - } - members[0]->m_groupData.head = true; - members[0]->m_groupData.locked = WASLOCKED; - } else - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); - - pDraggedWindow->m_isFloating = pWindowInsertAfter->m_isFloating; // match the floating state of the window - - pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); - - if (WINDOWINDEX == -1) - std::swap(pDraggedHead->m_groupData.head, pWindowInsertEnd->m_groupData.head); - m_window->setGroupCurrent(pDraggedWindow); - pDraggedWindow->applyGroupRules(); - pDraggedWindow->updateWindowDecos(); - g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow); + m_window->m_group->add(pDraggedWindow); if (!pDraggedWindow->getDecorationByType(DECORATION_GROUPBAR)) pDraggedWindow->addWindowDeco(makeUnique(pDraggedWindow)); @@ -519,7 +455,7 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) pressedCursorPos = pos; else if (e.state == WL_POINTER_BUTTON_STATE_RELEASED && pressedCursorPos == pos) - g_pXWaylandManager->sendCloseWindow(m_window->getGroupWindowByIndex(WINDOWINDEX)); + g_pXWaylandManager->sendCloseWindow(m_window->m_group->fromIndex(WINDOWINDEX)); return true; } @@ -532,17 +468,17 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo const auto STACKPAD = *PSTACKED && (BARRELATIVEY - (m_barHeight + *POUTERGAP) * WINDOWINDEX < *POUTERGAP); if (TABPAD || STACKPAD) { if (!g_pCompositor->isWindowActive(m_window.lock())) - Desktop::focusState()->rawWindowFocus(m_window.lock()); + Desktop::focusState()->rawWindowFocus(m_window.lock(), Desktop::FOCUS_REASON_CLICK); return true; } - PHLWINDOW pWindow = m_window->getGroupWindowByIndex(WINDOWINDEX); + PHLWINDOW pWindow = m_window->m_group->fromIndex(WINDOWINDEX); if (pWindow != m_window) - pWindow->setGroupCurrent(pWindow); + pWindow->m_group->setCurrent(pWindow); if (!g_pCompositor->isWindowActive(pWindow) && *PFOLLOWMOUSE != 3) - Desktop::focusState()->rawWindowFocus(pWindow); + Desktop::focusState()->rawWindowFocus(pWindow, Desktop::FOCUS_REASON_CLICK); if (pWindow->m_isFloating) g_pCompositor->changeWindowZOrder(pWindow, true); @@ -553,13 +489,13 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo bool CHyprGroupBarDecoration::onScrollOnDeco(const Vector2D& pos, const IPointer::SAxisEvent e) { static auto PGROUPBARSCROLLING = CConfigValue("group:groupbar:scrolling"); - if (!*PGROUPBARSCROLLING || m_window->m_groupData.pNextWindow.expired()) + if (!*PGROUPBARSCROLLING || !m_window->m_group) return false; if (e.delta > 0) - m_window->setGroupCurrent(m_window->m_groupData.pNextWindow.lock()); + m_window->m_group->moveCurrent(true); else - m_window->setGroupCurrent(m_window->getGroupPrevious()); + m_window->m_group->moveCurrent(false); return true; } diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 2982ba73..ce3a7a37 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -1,7 +1,7 @@ #include "DecorationPositioner.hpp" #include "../../desktop/view/Window.hpp" #include "../../managers/HookSystemManager.hpp" -#include "../../managers/LayoutManager.hpp" +#include "../../layout/target/Target.hpp" CDecorationPositioner::CDecorationPositioner() { static auto P = g_pHookSystem->hookDynamic("closeWindow", [this](void* call, SCallbackInfo& info, std::any data) { @@ -278,7 +278,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { if (WINDOWDATA->extents != SBoxExtents{{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}) { WINDOWDATA->extents = {{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}; - g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); + pWindow->layoutTarget()->recalc(); } } diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index d3027290..df410014 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -5,6 +5,7 @@ #include "../../protocols/core/Compositor.hpp" #include "../../protocols/DRMSyncobj.hpp" #include "../../managers/input/InputManager.hpp" +#include "../../layout/LayoutManager.hpp" #include "../Renderer.hpp" #include @@ -51,7 +52,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { if (!TEXTURE->m_texID) return; - const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_pInputManager->m_currentlyDraggedWindow && g_pInputManager->m_dragMode == MBIND_RESIZE; + const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); auto PSURFACE = Desktop::View::CWLSurface::fromResource(m_data.surface); @@ -163,7 +164,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { CBox CSurfacePassElement::getTexBox() { const double outputX = -m_data.pMonitor->m_position.x, outputY = -m_data.pMonitor->m_position.y; - const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_pInputManager->m_currentlyDraggedWindow && g_pInputManager->m_dragMode == MBIND_RESIZE; + const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE; auto PSURFACE = Desktop::View::CWLSurface::fromResource(m_data.surface); CBox windowBox; -- cgit v1.2.3