summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2026-02-21 21:30:39 +0000
committerGitHub <noreply@github.com>2026-02-21 21:30:39 +0000
commit723870337f299d4c80aa0048144f3a1ca1c885bd (patch)
treeca3279ae5dbc841f676c64d2f58f895de13cd3bf /src/render
parent51f8849e541f0a8150ac3a43fa928c1e299daf18 (diff)
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.
Diffstat (limited to 'src/render')
-rw-r--r--src/render/Renderer.cpp7
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.cpp122
-rw-r--r--src/render/decorations/DecorationPositioner.cpp4
-rw-r--r--src/render/pass/SurfacePassElement.cpp5
4 files changed, 38 insertions, 100 deletions
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<CWLSurfaceResource> 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 <ranges>
#include <pango/pangocairo.h>
#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<CTexture> m_tGradientActive = makeShared<CTexture>();
@@ -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<Hyprlang::INT>("group:groupbar:stacked");
static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
static auto PINNERGAP = CConfigValue<Hyprlang::INT>("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<Hyprlang::INT>("group:groupbar:stacked");
static auto PDRAGINTOGROUP = CConfigValue<Hyprlang::INT>("group:drag_into_group");
static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue<Hyprlang::INT>("group:merge_floated_into_tiled_on_groupbar");
static auto PMERGEGROUPSONGROUPBAR = CConfigValue<Hyprlang::INT>("group:merge_groups_on_groupbar");
- static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
- static auto PINNERGAP = CConfigValue<Hyprlang::INT>("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<PHLWINDOW> 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<CHyprGroupBarDecoration>(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<Hyprlang::INT>("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 <hyprutils/math/Box.hpp>
@@ -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;