diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2026-02-21 21:30:39 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-21 21:30:39 +0000 |
| commit | 723870337f299d4c80aa0048144f3a1ca1c885bd (patch) | |
| tree | ca3279ae5dbc841f676c64d2f58f895de13cd3bf /src/Compositor.cpp | |
| parent | 51f8849e541f0a8150ac3a43fa928c1e299daf18 (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/Compositor.cpp')
| -rw-r--r-- | src/Compositor.cpp | 138 |
1 files changed, 54 insertions, 84 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b722dab2..f05ff2f3 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -7,6 +7,7 @@ #include "desktop/state/FocusState.hpp" #include "desktop/history/WindowHistoryTracker.hpp" #include "desktop/history/WorkspaceHistoryTracker.hpp" +#include "desktop/view/Group.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" #include "config/ConfigWatcher.hpp" @@ -62,7 +63,6 @@ #include "managers/EventManager.hpp" #include "managers/HookSystemManager.hpp" #include "managers/ProtocolManager.hpp" -#include "managers/LayoutManager.hpp" #include "managers/WelcomeManager.hpp" #include "render/AsyncResourceGatherer.hpp" #include "plugins/PluginSystem.hpp" @@ -71,6 +71,8 @@ #include "debug/HyprDebugOverlay.hpp" #include "helpers/MonitorFrameScheduler.hpp" #include "i18n/Engine.hpp" +#include "layout/LayoutManager.hpp" +#include "layout/target/WindowTarget.hpp" #include <hyprutils/string/String.hpp> #include <aquamarine/input/Input.hpp> @@ -590,7 +592,7 @@ void CCompositor::cleanup() { g_pHyprRenderer.reset(); g_pHyprOpenGL.reset(); g_pConfigManager.reset(); - g_pLayoutManager.reset(); + g_layoutManager.reset(); g_pHyprError.reset(); g_pConfigManager.reset(); g_pKeybindManager.reset(); @@ -642,7 +644,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pHyprError = makeUnique<CHyprError>(); Log::logger->log(Log::DEBUG, "Creating the LayoutManager!"); - g_pLayoutManager = makeUnique<CLayoutManager>(); + g_layoutManager = makeUnique<Layout::CLayoutManager>(); Log::logger->log(Log::DEBUG, "Creating the TokenManager!"); g_pTokenManager = makeUnique<CTokenManager>(); @@ -1377,8 +1379,8 @@ void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) { m_windowsFadingOut.emplace_back(pWindow); } -PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { - if (!isDirection(dir)) +PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, Math::eDirection dir) { + if (dir == Math::DIRECTION_DEFAULT) return nullptr; const auto PMONITOR = pWindow->m_monitor.lock(); @@ -1395,8 +1397,8 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { return getWindowInDirection(WINDOWIDEALBB, PWORKSPACE, dir, pWindow, pWindow->m_isFloating); } -PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow, bool useVectorAngles) { - if (!isDirection(dir)) +PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, Math::eDirection dir, PHLWINDOW ignoreWindow, bool useVectorAngles) { + if (dir == Math::DIRECTION_DEFAULT) return nullptr; // 0 -> history, 1 -> shared length @@ -1431,28 +1433,27 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks double intersectLength = -1; switch (dir) { - case 'l': + case Math::DIRECTION_LEFT: if (STICKS(POSA.x, POSB.x + SIZEB.x)) { intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); } break; - case 'r': + case Math::DIRECTION_RIGHT: if (STICKS(POSA.x + SIZEA.x, POSB.x)) { intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); } break; - case 't': - case 'u': + case Math::DIRECTION_UP: if (STICKS(POSA.y, POSB.y + SIZEB.y)) { intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); } break; - case 'b': - case 'd': + case Math::DIRECTION_DOWN: if (STICKS(POSA.y + SIZEA.y, POSB.y)) { intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); } break; + default: break; } if (*PMETHOD == 0 /* history */) { @@ -1481,12 +1482,8 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks } } } else { - if (dir == 'u') - dir = 't'; - if (dir == 'd') - dir = 'b'; - - static const std::unordered_map<char, Vector2D> VECTORS = {{'r', {1, 0}}, {'t', {0, -1}}, {'b', {0, 1}}, {'l', {-1, 0}}}; + static const std::unordered_map<Math::eDirection, Vector2D> VECTORS = { + {Math::DIRECTION_RIGHT, {1, 0}}, {Math::DIRECTION_UP, {0, -1}}, {Math::DIRECTION_DOWN, {0, 1}}, {Math::DIRECTION_LEFT, {-1, 0}}}; // auto vectorAngles = [](const Vector2D& a, const Vector2D& b) -> double { @@ -1665,11 +1662,11 @@ CBox CCompositor::calculateX11WorkArea() { return workbox; } -PHLMONITOR CCompositor::getMonitorInDirection(const char& dir) { +PHLMONITOR CCompositor::getMonitorInDirection(Math::eDirection dir) { return getMonitorInDirection(Desktop::focusState()->monitor(), dir); } -PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const char& dir) { +PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, Math::eDirection dir) { if (!pSourceMonitor) return nullptr; @@ -1686,7 +1683,7 @@ PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const c const auto POSB = m->m_position; const auto SIZEB = m->m_size; switch (dir) { - case 'l': + case Math::DIRECTION_LEFT: if (STICKS(POSA.x, POSB.x + SIZEB.x)) { const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); if (INTERSECTLEN > longestIntersect) { @@ -1695,7 +1692,7 @@ PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const c } } break; - case 'r': + case Math::DIRECTION_RIGHT: if (STICKS(POSA.x + SIZEA.x, POSB.x)) { const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); if (INTERSECTLEN > longestIntersect) { @@ -1704,8 +1701,7 @@ PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const c } } break; - case 't': - case 'u': + case Math::DIRECTION_UP: if (STICKS(POSA.y, POSB.y + SIZEB.y)) { const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); if (INTERSECTLEN > longestIntersect) { @@ -1714,8 +1710,7 @@ PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const c } } break; - case 'b': - case 'd': + case Math::DIRECTION_DOWN: if (STICKS(POSA.y + SIZEA.y, POSB.y)) { const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); if (INTERSECTLEN > longestIntersect) { @@ -1724,6 +1719,7 @@ PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const c } } break; + default: break; } } @@ -1779,7 +1775,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor // additionally, move floating and fs windows manually if (w->m_isFloating) - *w->m_realPosition = w->m_realPosition->goal() - pMonitorA->m_position + pMonitorB->m_position; + w->layoutTarget()->setPositionGlobal(w->layoutTarget()->position().translate(-pMonitorA->m_position + pMonitorB->m_position)); if (w->isFullscreen()) { *w->m_realPosition = pMonitorB->m_position; @@ -1804,7 +1800,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor // additionally, move floating and fs windows manually if (w->m_isFloating) - *w->m_realPosition = w->m_realPosition->goal() - pMonitorB->m_position + pMonitorA->m_position; + w->layoutTarget()->setPositionGlobal(w->layoutTarget()->position().translate(-pMonitorB->m_position + pMonitorA->m_position)); if (w->isFullscreen()) { *w->m_realPosition = pMonitorA->m_position; @@ -1818,8 +1814,8 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor pMonitorA->m_activeWorkspace = PWORKSPACEB; pMonitorB->m_activeWorkspace = PWORKSPACEA; - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorA->m_id); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorB->m_id); + g_layoutManager->recalculateMonitor(pMonitorA); + g_layoutManager->recalculateMonitor(pMonitorB); g_pDesktopAnimationManager->setFullscreenFadeAnimation( PWORKSPACEB, PWORKSPACEB->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); @@ -1831,7 +1827,8 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor Desktop::focusState()->fullWindowFocus( LASTWIN ? LASTWIN : (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), - Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING))); + Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING)), + Desktop::FOCUS_REASON_DESKTOP_STATE_CHANGE); const auto PNEWWORKSPACE = pMonitorA->m_id == Desktop::focusState()->monitor()->m_id ? PWORKSPACEB : PWORKSPACEA; g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspace", .data = PNEWWORKSPACE->m_name}); @@ -1853,7 +1850,7 @@ PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { if (name == "current") return Desktop::focusState()->monitor(); else if (isDirection(name)) - return getMonitorInDirection(name[0]); + return getMonitorInDirection(Math::fromChar(name[0])); else if (name[0] == '+' || name[0] == '-') { // relative @@ -1989,17 +1986,18 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo if (w->m_isMapped && !w->isHidden()) { if (POLDMON) { if (w->m_isFloating) - *w->m_realPosition = w->m_realPosition->goal() - POLDMON->m_position + pMonitor->m_position; + w->layoutTarget()->setPositionGlobal(w->layoutTarget()->position().translate(-POLDMON->m_position + pMonitor->m_position)); if (w->isFullscreen()) { *w->m_realPosition = pMonitor->m_position; *w->m_realSize = pMonitor->m_size; } } else - *w->m_realPosition = Vector2D{ - (pMonitor->m_size.x != 0) ? sc<int>(w->m_realPosition->goal().x) % sc<int>(pMonitor->m_size.x) : 0, - (pMonitor->m_size.y != 0) ? sc<int>(w->m_realPosition->goal().y) % sc<int>(pMonitor->m_size.y) : 0, - }; + w->layoutTarget()->setPositionGlobal(CBox{Vector2D{ + (pMonitor->m_size.x != 0) ? sc<int>(w->m_realPosition->goal().x) % sc<int>(pMonitor->m_size.x) : 0, + (pMonitor->m_size.y != 0) ? sc<int>(w->m_realPosition->goal().y) % sc<int>(pMonitor->m_size.y) : 0, + }, + w->layoutTarget()->position().size()}); } w->updateToplevel(); @@ -2027,7 +2025,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo pWorkspace->m_events.activeChanged.emit(); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->m_id); + g_layoutManager->recalculateMonitor(pMonitor); g_pDesktopAnimationManager->startAnimation(pWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); pWorkspace->m_visible = true; @@ -2040,7 +2038,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo // finalize if (POLDMON) { - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->m_id); + g_layoutManager->recalculateMonitor(POLDMON); if (valid(POLDMON->m_activeWorkspace)) g_pDesktopAnimationManager->setFullscreenFadeAnimation(POLDMON->m_activeWorkspace, POLDMON->m_activeWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : @@ -2138,15 +2136,16 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, Desktop::Vie PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE); PWINDOW->updateDecorationValues(); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); + g_layoutManager->recalculateMonitor(PMONITOR); return; } - g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE); + PWORKSPACE->m_fullscreenMode = EFFECTIVE_MODE; + PWORKSPACE->m_hasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE; + + g_layoutManager->fullscreenRequestForTarget(PWINDOW->layoutTarget(), CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE); PWINDOW->m_fullscreenState.internal = state.internal; - PWORKSPACE->m_fullscreenMode = EFFECTIVE_MODE; - PWORKSPACE->m_hasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE; g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string(sc<int>(EFFECTIVE_MODE) != FSMODE_NONE)}); EMIT_HOOK_EVENT("fullscreen", PWINDOW); @@ -2155,7 +2154,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, Desktop::Vie Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE); PWINDOW->updateDecorationValues(); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); + g_layoutManager->recalculateMonitor(PMONITOR); // make all windows and layers on the same workspace under the fullscreen window for (auto const& w : m_windows) { @@ -2268,7 +2267,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) { } for (auto const& w : g_pCompositor->m_windows) { - if (!w->m_isMapped || (w->isHidden() && !g_pLayoutManager->getCurrentLayout()->isWindowReachable(w))) + if (!w->m_isMapped) continue; switch (mode) { @@ -2573,59 +2572,30 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor setWindowFullscreenInternal(pWindow, FSMODE_NONE); const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow(); - const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true); + const int visibleWindowsOnWorkspace = pWorkspace->getWindows(true, std::nullopt, true); const auto POSTOMON = pWindow->m_realPosition->goal() - (pWindow->m_monitor ? pWindow->m_monitor->m_position : Vector2D{}); const auto PWORKSPACEMONITOR = pWorkspace->m_monitor.lock(); - if (!pWindow->m_isFloating) - g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); - pWindow->moveToWorkspace(pWorkspace); pWindow->m_monitor = pWorkspace->m_monitor; static auto PGROUPONMOVETOWORKSPACE = CConfigValue<Hyprlang::INT>("group:group_on_movetoworkspace"); - if (*PGROUPONMOVETOWORKSPACE && visibleWindowsOnWorkspace == 1 && pFirstWindowOnWorkspace && pFirstWindowOnWorkspace != pWindow && - pFirstWindowOnWorkspace->m_groupData.pNextWindow.lock() && pWindow->canBeGroupedInto(pFirstWindowOnWorkspace)) { - - pWindow->m_isFloating = pFirstWindowOnWorkspace->m_isFloating; // match the floating state. Needed to group tiled into floated and vice versa. - if (!pWindow->m_groupData.pNextWindow.expired()) { - PHLWINDOW next = pWindow->m_groupData.pNextWindow.lock(); - while (next != pWindow) { - next->m_isFloating = pFirstWindowOnWorkspace->m_isFloating; // match the floating state of group members - next = next->m_groupData.pNextWindow.lock(); - } - } - - static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current"); - (*USECURRPOS ? pFirstWindowOnWorkspace : pFirstWindowOnWorkspace->getGroupTail())->insertWindowToGroup(pWindow); - - pFirstWindowOnWorkspace->setGroupCurrent(pWindow); - pWindow->updateWindowDecos(); - g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow)); - + if (*PGROUPONMOVETOWORKSPACE && visibleWindowsOnWorkspace == 1 && pFirstWindowOnWorkspace && pFirstWindowOnWorkspace != pWindow && pFirstWindowOnWorkspace->m_group && + pWindow->canBeGroupedInto(pFirstWindowOnWorkspace->m_group)) { + pFirstWindowOnWorkspace->m_group->add(pWindow); } else { - if (!pWindow->m_isFloating) - g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); - if (pWindow->m_isFloating) - *pWindow->m_realPosition = POSTOMON + PWORKSPACEMONITOR->m_position; + pWindow->layoutTarget()->setPositionGlobal(CBox{POSTOMON + PWORKSPACEMONITOR->m_position, pWindow->layoutTarget()->position().size()}); } pWindow->updateToplevel(); pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ON_WORKSPACE); pWindow->uncacheWindowDecos(); - pWindow->updateGroupOutputs(); - if (!pWindow->m_groupData.pNextWindow.expired()) { - PHLWINDOW next = pWindow->m_groupData.pNextWindow.lock(); - while (next != pWindow) { - next->updateToplevel(); - next = next->m_groupData.pNextWindow.lock(); - } - } + if (pWindow->m_group) + pWindow->m_group->updateWorkspace(pWorkspace); + + g_layoutManager->newTarget(pWindow->layoutTarget(), pWorkspace->m_space); if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FULLSCREENMODE); |
