desktop: rewrite reserved area handling + improve tests (#12383)

This commit is contained in:
Vaxry 2025-12-05 14:16:22 +00:00 committed by GitHub
parent d5c52ef58e
commit 9264436f35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 818 additions and 413 deletions

View file

@ -41,35 +41,39 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
children[0]->recalcSizePosRecursive(force);
children[1]->recalcSizePosRecursive(force);
} else {
layout->applyNodeDataToWindow(this, force);
layout->applyNodeDataToWindow(self.lock(), force);
}
}
void SDwindleNodeData::applyRootBox() {
box = layout->workAreaOnWorkspace(g_pCompositor->getWorkspaceByID(workspaceID));
}
int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) {
int no = 0;
for (auto const& n : m_dwindleNodesData) {
if (n.workspaceID == id && n.valid)
if (n->workspaceID == id && n->valid)
++no;
}
return no;
}
SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) {
SP<SDwindleNodeData> CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) {
for (auto& n : m_dwindleNodesData) {
if (n.workspaceID == id && validMapped(n.pWindow))
return &n;
if (n->workspaceID == id && validMapped(n->pWindow))
return n;
}
return nullptr;
}
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) {
SDwindleNodeData* res = nullptr;
double distClosest = -1;
SP<SDwindleNodeData> CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) {
SP<SDwindleNodeData> res = nullptr;
double distClosest = -1;
for (auto& n : m_dwindleNodesData) {
if (n.workspaceID == id && validMapped(n.pWindow)) {
auto distAnother = vecToRectDistanceSquared(point, n.box.pos(), n.box.pos() + n.box.size());
if (n->workspaceID == id && validMapped(n->pWindow)) {
auto distAnother = vecToRectDistanceSquared(point, n->box.pos(), n->box.pos() + n->box.size());
if (!res || distAnother < distClosest) {
res = &n;
res = n;
distClosest = distAnother;
}
}
@ -77,30 +81,32 @@ SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEI
return res;
}
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) {
SP<SDwindleNodeData> CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) {
for (auto& n : m_dwindleNodesData) {
if (n.pWindow.lock() == pWindow && !n.isNode)
return &n;
if (n->pWindow.lock() == pWindow && !n->isNode)
return n;
}
return nullptr;
}
SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) {
SP<SDwindleNodeData> CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) {
for (auto& n : m_dwindleNodesData) {
if (!n.pParent && n.workspaceID == id)
return &n;
if (!n->pParent && n->workspaceID == id)
return n;
}
return nullptr;
}
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool force) {
void CHyprDwindleLayout::applyNodeDataToWindow(SP<SDwindleNodeData> pNode, bool force) {
// Don't set nodes, only windows.
if (pNode->isNode)
return;
PHLMONITOR PMONITOR = nullptr;
const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID);
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
for (auto const& m : g_pCompositor->m_monitors) {
if (m->activeSpecialWorkspaceID() == pNode->workspaceID) {
@ -108,19 +114,20 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
break;
}
}
} else if (const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID); WS)
} else if (WS)
PMONITOR = WS->m_monitor.lock();
if (!PMONITOR) {
if (!PMONITOR || !WS) {
Debug::log(ERR, "Orphaned Node {}!!", pNode);
return;
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->box.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->box.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y);
const auto MONITOR_WORKAREA = workAreaOnWorkspace(WS);
const bool DISPLAYLEFT = STICKS(pNode->box.x, MONITOR_WORKAREA.x);
const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w);
const bool DISPLAYTOP = STICKS(pNode->box.y, MONITOR_WORKAREA.y);
const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h);
const auto PWINDOW = pNode->pWindow.lock();
// get specific gaps and rules for this workspace,
@ -139,13 +146,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
PWINDOW->updateWindowData();
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
auto* const PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
auto* const PGAPSOUT = sc<CCssGapData*>((PGAPSOUTDATA.ptr())->getData());
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
auto* const PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
CBox nodeBox = pNode->box;
nodeBox.round();
@ -163,7 +167,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
Vector2D ratioPadding;
if ((*REQUESTEDRATIO).y != 0 && !pNode->pParent) {
const Vector2D originalSize = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight;
const Vector2D originalSize = MONITOR_WORKAREA.size();
const double requestedRatio = (*REQUESTEDRATIO).x / (*REQUESTEDRATIO).y;
const double originalRatio = originalSize.x / originalSize.y;
@ -181,9 +185,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
}
}
const auto GAPOFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? gapsOut.m_left : gapsIn.m_left), sc<double>(DISPLAYTOP ? gapsOut.m_top : gapsIn.m_top));
const auto GAPOFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? 0 : gapsIn.m_left), sc<double>(DISPLAYTOP ? 0 : gapsIn.m_top));
const auto GAPOFFSETBOTTOMRIGHT = Vector2D(sc<double>(DISPLAYRIGHT ? gapsOut.m_right : gapsIn.m_right), sc<double>(DISPLAYBOTTOM ? gapsOut.m_bottom : gapsIn.m_bottom));
const auto GAPOFFSETBOTTOMRIGHT = Vector2D(sc<double>(DISPLAYRIGHT ? 0 : gapsIn.m_right), sc<double>(DISPLAYBOTTOM ? 0 : gapsIn.m_bottom));
calcPos = calcPos + GAPOFFSETTOPLEFT + ratioPadding / 2;
calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding;
@ -222,20 +226,17 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
if (*PCLAMP_TILED) {
const auto borderSize = PWINDOW->getRealBorderSize();
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
Vector2D monitorAvailable = MONITOR_WORKAREA.size() - Vector2D{2.0 * borderSize, 2.0 * borderSize};
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} :
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
calcSize = calcSize.clamp(minSize, maxSize);
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} :
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
calcSize = calcSize.clamp(minSize, maxSize);
calcPos += (availableSpace - calcSize) / 2.0;
calcPos.x = std::clamp(calcPos.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x + gapsOut.m_left + borderSize,
PMONITOR->m_size.x + PMONITOR->m_position.x - PMONITOR->m_reservedBottomRight.x - gapsOut.m_right - calcSize.x - borderSize);
calcPos.y = std::clamp(calcPos.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y + gapsOut.m_top + borderSize,
PMONITOR->m_size.y + PMONITOR->m_position.y - PMONITOR->m_reservedBottomRight.y - gapsOut.m_bottom - calcSize.y - borderSize);
calcPos.x = std::clamp(calcPos.x, MONITOR_WORKAREA.x + borderSize, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w - calcSize.x - borderSize);
calcPos.y = std::clamp(calcPos.y, MONITOR_WORKAREA.y + borderSize, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h - calcSize.y - borderSize);
}
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
@ -271,8 +272,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
if (pWindow->m_isFloating)
return;
m_dwindleNodesData.emplace_back();
const auto PNODE = &m_dwindleNodesData.back();
const auto PNODE = m_dwindleNodesData.emplace_back(makeShared<SDwindleNodeData>());
PNODE->self = PNODE;
const auto PMONITOR = pWindow->m_monitor.lock();
@ -288,10 +289,10 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
PNODE->isNode = false;
PNODE->layout = this;
SDwindleNodeData* OPENINGON;
SP<SDwindleNodeData> OPENINGON;
const auto MOUSECOORDS = m_overrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
const auto MOUSECOORDS = m_overrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
if (PMONITOR->m_id == MONFROMCURSOR->m_id &&
(PNODE->workspaceID == PMONITOR->activeWorkspaceID() || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->m_activeSpecialWorkspace)) && !*PUSEACTIVE) {
@ -326,7 +327,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) {
// we can't continue. make it floating.
pWindow->m_isFloating = true;
m_dwindleNodesData.remove(*PNODE);
std::erase(m_dwindleNodesData, PNODE);
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow);
return;
}
@ -334,8 +335,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
// last fail-safe to avoid duplicate fullscreens
if ((!OPENINGON || OPENINGON->pWindow.lock() == pWindow) && getNodesOnWorkspace(PNODE->workspaceID) > 1) {
for (auto& node : m_dwindleNodesData) {
if (node.workspaceID == PNODE->workspaceID && node.pWindow.lock() && node.pWindow.lock() != pWindow) {
OPENINGON = &node;
if (node->workspaceID == PNODE->workspaceID && node->pWindow.lock() && node->pWindow.lock() != pWindow) {
OPENINGON = node;
break;
}
}
@ -343,17 +344,14 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
// if it's the first, it's easy. Make it fullscreen.
if (!OPENINGON || OPENINGON->pWindow.lock() == pWindow) {
PNODE->box = CBox{PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight};
PNODE->applyRootBox();
applyNodeDataToWindow(PNODE);
return;
}
// get the node under our cursor
m_dwindleNodesData.emplace_back();
const auto NEWPARENT = &m_dwindleNodesData.back();
const auto NEWPARENT = m_dwindleNodesData.emplace_back(makeShared<SDwindleNodeData>());
// make the parent have the OPENINGON's stats
NEWPARENT->box = OPENINGON->box;
@ -361,6 +359,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
NEWPARENT->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node
NEWPARENT->splitRatio = std::clamp(*PDEFAULTSPLIT, 0.1f, 1.9f);
NEWPARENT->layout = this;
static auto PWIDTHMULTIPLIER = CConfigValue<Hyprlang::FLOAT>("dwindle:split_width_multiplier");
@ -503,7 +502,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
if (!PPARENT) {
Debug::log(LOG, "Removing last node (dwindle)");
m_dwindleNodesData.remove(*PNODE);
std::erase(m_dwindleNodesData, PNODE);
return;
}
@ -528,8 +527,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
else
PSIBLING->recalcSizePosRecursive();
m_dwindleNodesData.remove(*PPARENT);
m_dwindleNodesData.remove(*PNODE);
std::erase(m_dwindleNodesData, PPARENT);
std::erase(m_dwindleNodesData, PNODE);
pWindow->m_workspace->updateWindows();
}
@ -568,15 +567,17 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) {
*PFULLWINDOW->m_realPosition = PMONITOR->m_position;
*PFULLWINDOW->m_realSize = PMONITOR->m_size;
} else if (pWorkspace->m_fullscreenMode == FSMODE_MAXIMIZED) {
SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.box = {PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight};
fakeNode.workspaceID = pWorkspace->m_id;
PFULLWINDOW->m_position = fakeNode.box.pos();
PFULLWINDOW->m_size = fakeNode.box.size();
fakeNode.ignoreFullscreenChecks = true;
SP<SDwindleNodeData> fakeNode = makeShared<SDwindleNodeData>();
fakeNode->self = fakeNode;
fakeNode->pWindow = PFULLWINDOW;
fakeNode->box = PMONITOR->logicalBoxMinusReserved();
fakeNode->workspaceID = pWorkspace->m_id;
PFULLWINDOW->m_position = fakeNode->box.pos();
PFULLWINDOW->m_size = fakeNode->box.size();
fakeNode->ignoreFullscreenChecks = true;
fakeNode->layout = this;
applyNodeDataToWindow(&fakeNode);
applyNodeDataToWindow(fakeNode);
}
// if has fullscreen, don't calculate the rest
@ -586,7 +587,7 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) {
const auto TOPNODE = getMasterNodeOnWorkspace(pWorkspace->m_id);
if (TOPNODE) {
TOPNODE->box = {PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight};
TOPNODE->applyRootBox();
TOPNODE->recalcSizePosRecursive();
}
}
@ -622,11 +623,12 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("dwindle:smart_resizing");
// get some data about our window
const auto PMONITOR = PWINDOW->m_monitor.lock();
const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x);
const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y);
const auto PMONITOR = PWINDOW->m_monitor.lock();
const auto MONITOR_WORKAREA = PMONITOR->logicalBoxMinusReserved();
const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, MONITOR_WORKAREA.x);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w);
const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, MONITOR_WORKAREA.y);
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h);
if (PWINDOW->m_isPseudotiled) {
if (!m_pseudoDragFlags.started) {
@ -682,18 +684,18 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
if (*PSMARTRESIZING == 1) {
// Identify inner and outer nodes for both directions
SDwindleNodeData* PVOUTER = nullptr;
SDwindleNodeData* PVINNER = nullptr;
SDwindleNodeData* PHOUTER = nullptr;
SDwindleNodeData* PHINNER = nullptr;
SP<SDwindleNodeData> PVOUTER = nullptr;
SP<SDwindleNodeData> PVINNER = nullptr;
SP<SDwindleNodeData> PHOUTER = nullptr;
SP<SDwindleNodeData> PHINNER = nullptr;
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT || DISPLAYRIGHT;
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT || DISPLAYBOTTOM;
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT || DISPLAYLEFT;
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT || DISPLAYTOP;
const auto NONE = corner == CORNER_NONE;
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT || DISPLAYRIGHT;
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT || DISPLAYBOTTOM;
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT || DISPLAYLEFT;
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT || DISPLAYTOP;
const auto NONE = corner == CORNER_NONE;
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) {
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent.lock()) {
const auto PPARENT = PCURRENT->pParent;
if (!PVOUTER && PPARENT->splitTop && (NONE || (TOP && PPARENT->children[1] == PCURRENT) || (BOTTOM && PPARENT->children[0] == PCURRENT)))
@ -833,15 +835,17 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
// We make a fake "only" node and apply
// To keep consistent with the settings without C+P code
SDwindleNodeData fakeNode;
fakeNode.pWindow = pWindow;
fakeNode.box = {PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight};
fakeNode.workspaceID = pWindow->workspaceID();
pWindow->m_position = fakeNode.box.pos();
pWindow->m_size = fakeNode.box.size();
fakeNode.ignoreFullscreenChecks = true;
SP<SDwindleNodeData> fakeNode = makeShared<SDwindleNodeData>();
fakeNode->self = fakeNode;
fakeNode->pWindow = pWindow;
fakeNode->box = PMONITOR->logicalBoxMinusReserved();
fakeNode->workspaceID = pWindow->workspaceID();
pWindow->m_position = fakeNode->box.pos();
pWindow->m_size = fakeNode->box.size();
fakeNode->ignoreFullscreenChecks = true;
fakeNode->layout = this;
applyNodeDataToWindow(&fakeNode);
applyNodeDataToWindow(fakeNode);
}
}
@ -1092,10 +1096,10 @@ void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) {
// instead of [getMasterNodeOnWorkspace], we walk back to root since we need
// to know which children of root is our ancestor
auto pAncestor = PNODE, pRoot = PNODE->pParent;
auto pAncestor = PNODE, pRoot = PNODE->pParent.lock();
while (pRoot->pParent) {
pAncestor = pRoot;
pRoot = pRoot->pParent;
pRoot = pRoot->pParent.lock();
}
auto& pSwap = pRoot->children[0] == pAncestor ? pRoot->children[1] : pRoot->children[0];

View file

@ -13,24 +13,25 @@ class CHyprDwindleLayout;
enum eFullscreenMode : int8_t;
struct SDwindleNodeData {
SDwindleNodeData* pParent = nullptr;
bool isNode = false;
WP<SDwindleNodeData> pParent;
bool isNode = false;
PHLWINDOWREF pWindow;
PHLWINDOWREF pWindow;
std::array<SDwindleNodeData*, 2> children = {nullptr, nullptr};
std::array<WP<SDwindleNodeData>, 2> children = {};
WP<SDwindleNodeData> self;
bool splitTop = false; // for preserve_split
bool splitTop = false; // for preserve_split
CBox box = {0};
CBox box = {0};
WORKSPACEID workspaceID = WORKSPACE_INVALID;
WORKSPACEID workspaceID = WORKSPACE_INVALID;
float splitRatio = 1.f;
float splitRatio = 1.f;
bool valid = true;
bool valid = true;
bool ignoreFullscreenChecks = false;
bool ignoreFullscreenChecks = false;
// For list lookup
bool operator==(const SDwindleNodeData& rhs) const {
@ -39,6 +40,7 @@ struct SDwindleNodeData {
}
void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false);
void applyRootBox();
CHyprDwindleLayout* layout = nullptr;
};
@ -65,7 +67,7 @@ class CHyprDwindleLayout : public IHyprLayout {
virtual void onDisable();
private:
std::list<SDwindleNodeData> m_dwindleNodesData;
std::vector<SP<SDwindleNodeData>> m_dwindleNodesData;
struct {
bool started = false;
@ -77,12 +79,12 @@ class CHyprDwindleLayout : public IHyprLayout {
std::optional<Vector2D> m_overrideFocalPoint; // for onWindowCreatedTiling.
int getNodesOnWorkspace(const WORKSPACEID&);
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
void applyNodeDataToWindow(SP<SDwindleNodeData>, bool force = false);
void calculateWorkspace(const PHLWORKSPACE& pWorkspace);
SDwindleNodeData* getNodeFromWindow(PHLWINDOW);
SDwindleNodeData* getFirstNodeOnWorkspace(const WORKSPACEID&);
SDwindleNodeData* getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&);
SDwindleNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&);
SP<SDwindleNodeData> getNodeFromWindow(PHLWINDOW);
SP<SDwindleNodeData> getFirstNodeOnWorkspace(const WORKSPACEID&);
SP<SDwindleNodeData> getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&);
SP<SDwindleNodeData> getMasterNodeOnWorkspace(const WORKSPACEID&);
void toggleSplit(PHLWINDOW);
void swapSplit(PHLWINDOW);
@ -94,13 +96,13 @@ class CHyprDwindleLayout : public IHyprLayout {
};
template <typename CharT>
struct std::formatter<SDwindleNodeData*, CharT> : std::formatter<CharT> {
struct std::formatter<SP<SDwindleNodeData>, CharT> : std::formatter<CharT> {
template <typename FormatContext>
auto format(const SDwindleNodeData* const& node, FormatContext& ctx) const {
auto format(const SP<SDwindleNodeData>& node, FormatContext& ctx) const {
auto out = ctx.out();
if (!node)
return std::format_to(out, "[Node nullptr]");
std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", rc<uintptr_t>(node), node->workspaceID, node->box.pos(), node->box.size());
std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", rc<uintptr_t>(node.get()), node->workspaceID, node->box.pos(), node->box.size());
if (!node->isNode && !node->pWindow.expired())
std::format_to(out, ", window: {:x}", node->pWindow.lock());
return std::format_to(out, "]");

View file

@ -503,32 +503,35 @@ void IHyprLayout::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWIND
const auto EXTENTNONE = SBoxExtents{{0, 0}, {0, 0}};
const auto* EXTENTDIFF = *SNAPBORDEROVERLAP ? &EXTENTS : &EXTENTNONE;
const auto MON = DRAGGINGWINDOW->m_monitor.lock();
const auto* GAPSOUT = *SNAPRESPECTGAPS ? sc<CCssGapData*>(PGAPSOUT.ptr()->getData()) : &GAPSNONE;
SRange monX = {MON->m_position.x + MON->m_reservedTopLeft.x + GAPSOUT->m_left, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - GAPSOUT->m_right};
SRange monY = {MON->m_position.y + MON->m_reservedTopLeft.y + GAPSOUT->m_top, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - GAPSOUT->m_bottom};
const auto* GAPSOUT = *SNAPRESPECTGAPS ? sc<CCssGapData*>(PGAPSOUT.ptr()->getData()) : &GAPSNONE;
const auto WORK_AREA = Desktop::CReservedArea{GAPSOUT->m_top, GAPSOUT->m_right, GAPSOUT->m_bottom, GAPSOUT->m_left}.apply(MON->logicalBoxMinusReserved());
SRange monX = {WORK_AREA.x, WORK_AREA.x + WORK_AREA.w};
SRange monY = {WORK_AREA.y, WORK_AREA.y + WORK_AREA.h};
const bool HAS_LEFT = MON->m_reservedArea.left() > 0;
const bool HAS_TOP = MON->m_reservedArea.top() > 0;
const bool HAS_BOTTOM = MON->m_reservedArea.bottom() > 0;
const bool HAS_RIGHT = MON->m_reservedArea.right() > 0;
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) &&
((MON->m_reservedTopLeft.x > 0 && canSnap(sourceX.start, monX.start, GAPSIZE)) ||
canSnap(sourceX.start, (monX.start -= MON->m_reservedTopLeft.x + EXTENTDIFF->topLeft.x), GAPSIZE))) {
((HAS_LEFT && canSnap(sourceX.start, monX.start, GAPSIZE)) || canSnap(sourceX.start, (monX.start -= MON->m_reservedArea.left() + EXTENTDIFF->topLeft.x), GAPSIZE))) {
SNAP(sourceX.start, sourceX.end, monX.start);
snaps |= SNAP_LEFT;
}
if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) &&
((MON->m_reservedBottomRight.x > 0 && canSnap(sourceX.end, monX.end, GAPSIZE)) ||
canSnap(sourceX.end, (monX.end += MON->m_reservedBottomRight.x + EXTENTDIFF->bottomRight.x), GAPSIZE))) {
((HAS_RIGHT && canSnap(sourceX.end, monX.end, GAPSIZE)) || canSnap(sourceX.end, (monX.end += MON->m_reservedArea.right() + EXTENTDIFF->bottomRight.x), GAPSIZE))) {
SNAP(sourceX.end, sourceX.start, monX.end);
snaps |= SNAP_RIGHT;
}
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) &&
((MON->m_reservedTopLeft.y > 0 && canSnap(sourceY.start, monY.start, GAPSIZE)) ||
canSnap(sourceY.start, (monY.start -= MON->m_reservedTopLeft.y + EXTENTDIFF->topLeft.y), GAPSIZE))) {
((HAS_TOP && canSnap(sourceY.start, monY.start, GAPSIZE)) || canSnap(sourceY.start, (monY.start -= MON->m_reservedArea.top() + EXTENTDIFF->topLeft.y), GAPSIZE))) {
SNAP(sourceY.start, sourceY.end, monY.start);
snaps |= SNAP_UP;
}
if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) &&
((MON->m_reservedBottomRight.y > 0 && canSnap(sourceY.end, monY.end, GAPSIZE)) ||
canSnap(sourceY.end, (monY.end += MON->m_reservedBottomRight.y + EXTENTDIFF->bottomRight.y), GAPSIZE))) {
((HAS_BOTTOM && canSnap(sourceY.end, monY.end, GAPSIZE)) || canSnap(sourceY.end, (monY.end += MON->m_reservedArea.bottom() + EXTENTDIFF->bottomRight.y), GAPSIZE))) {
SNAP(sourceY.end, sourceY.start, monY.end);
snaps |= SNAP_DOWN;
}
@ -832,7 +835,7 @@ void IHyprLayout::fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional<CBox> tb
const auto EXTENTS = w->getWindowExtentsUnified(RESERVED_EXTENTS | INPUT_EXTENTS);
CBox targetBoxMonLocal = tb.value_or(w->getWindowMainSurfaceBox()).translate(-PMONITOR->m_position).addExtents(EXTENTS);
const auto MONITOR_LOCAL_BOX = PMONITOR->logicalBoxMinusExtents().translate(-PMONITOR->m_position);
const auto MONITOR_LOCAL_BOX = PMONITOR->logicalBoxMinusReserved().translate(-PMONITOR->m_position);
if (targetBoxMonLocal.w < MONITOR_LOCAL_BOX.w) {
if (targetBoxMonLocal.x < MONITOR_LOCAL_BOX.x)
@ -1039,3 +1042,22 @@ bool IHyprLayout::updateDragWindow() {
return false;
}
CBox IHyprLayout::workAreaOnWorkspace(const PHLWORKSPACE& pWorkspace) {
if (!pWorkspace || !pWorkspace->m_monitor)
return {};
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(pWorkspace);
auto workArea = pWorkspace->m_monitor->logicalBoxMinusReserved();
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
auto* const PGAPSOUT = sc<CCssGapData*>((PGAPSOUTDATA.ptr())->getData());
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
Desktop::CReservedArea reservedGaps{gapsOut.m_top, gapsOut.m_right, gapsOut.m_bottom, gapsOut.m_left};
reservedGaps.applyip(workArea);
return workArea;
}

View file

@ -230,6 +230,12 @@ class IHyprLayout {
*/
virtual void fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional<CBox> targetBox = std::nullopt);
/*
Returns a logical box describing the work area on a workspace
(monitor size - reserved - gapsOut)
*/
virtual CBox workAreaOnWorkspace(const PHLWORKSPACE& pWorkspace);
private:
int m_mouseMoveEventCount;
Vector2D m_beginDragXY;

View file

@ -322,8 +322,9 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
} else if (pWorkspace->m_fullscreenMode == FSMODE_MAXIMIZED) {
SMasterNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->m_position + PMONITOR->m_reservedTopLeft;
fakeNode.size = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight;
const auto WORKAREA = PMONITOR->logicalBoxMinusReserved();
fakeNode.position = WORKAREA.pos();
fakeNode.size = WORKAREA.size();
fakeNode.workspaceID = pWorkspace->m_id;
PFULLWINDOW->m_position = fakeNode.position;
PFULLWINDOW->m_size = fakeNode.size;
@ -351,13 +352,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_id);
const auto WINDOWS = getNodesOnWorkspace(pWorkspace->m_id);
const auto STACKWINDOWS = WINDOWS - MASTERS;
const auto WSSIZE = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight;
const auto WSPOS = PMONITOR->m_position + PMONITOR->m_reservedTopLeft;
const auto WORKAREA = workAreaOnWorkspace(pWorkspace);
if (orientation == ORIENTATION_CENTER) {
if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) {
if (STACKWINDOWS >= *SLAVECOUNTFORCENTER)
centerMasterWindow = true;
} else {
else {
if (*CMFALLBACK == "left")
orientation = ORIENTATION_LEFT;
else if (*CMFALLBACK == "right")
@ -371,7 +371,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
}
}
const float totalSize = (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) ? WSSIZE.x : WSSIZE.y;
const float totalSize = (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) ? WORKAREA.w : WORKAREA.h;
const float masterAverageSize = totalSize / MASTERS;
const float slaveAverageSize = totalSize / STACKWINDOWS;
float masterAccumulatedSize = 0;
@ -394,32 +394,32 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
if (WINDOWS == 1 && !centerMasterWindow) {
static auto PALWAYSKEEPPOSITION = CConfigValue<Hyprlang::INT>("master:always_keep_position");
if (*PALWAYSKEEPPOSITION) {
const float WIDTH = WSSIZE.x * PMASTERNODE->percMaster;
const float WIDTH = WORKAREA.w * PMASTERNODE->percMaster;
float nextX = 0;
if (orientation == ORIENTATION_RIGHT)
nextX = WSSIZE.x - WIDTH;
nextX = WORKAREA.w - WIDTH;
else if (orientation == ORIENTATION_CENTER)
nextX = (WSSIZE.x - WIDTH) / 2;
nextX = (WORKAREA.w - WIDTH) / 2;
PMASTERNODE->size = Vector2D(WIDTH, WSSIZE.y);
PMASTERNODE->position = WSPOS + Vector2D(nextX, 0.0);
PMASTERNODE->size = Vector2D(WIDTH, WORKAREA.h);
PMASTERNODE->position = WORKAREA.pos() + Vector2D(nextX, 0.0);
} else {
PMASTERNODE->size = WSSIZE;
PMASTERNODE->position = WSPOS;
PMASTERNODE->size = WORKAREA.size();
PMASTERNODE->position = WORKAREA.pos();
}
applyNodeDataToWindow(PMASTERNODE);
return;
} else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
const float HEIGHT = STACKWINDOWS != 0 ? WSSIZE.y * PMASTERNODE->percMaster : WSSIZE.y;
float widthLeft = WSSIZE.x;
const float HEIGHT = STACKWINDOWS != 0 ? WORKAREA.h * PMASTERNODE->percMaster : WORKAREA.h;
float widthLeft = WORKAREA.w;
int mastersLeft = MASTERS;
float nextX = 0;
float nextY = 0;
if (orientation == ORIENTATION_BOTTOM)
nextY = WSSIZE.y - HEIGHT;
nextY = WORKAREA.h - HEIGHT;
for (auto& nd : m_masterNodesData) {
if (nd.workspaceID != pWorkspace->m_id || !nd.isMaster)
@ -430,12 +430,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
WIDTH = widthLeft * 0.9f;
if (*PSMARTRESIZING) {
nd.percSize *= WSSIZE.x / masterAccumulatedSize;
nd.percSize *= WORKAREA.w / masterAccumulatedSize;
WIDTH = masterAverageSize * nd.percSize;
}
nd.size = Vector2D(WIDTH, HEIGHT);
nd.position = WSPOS + Vector2D(nextX, nextY);
nd.position = WORKAREA.pos() + Vector2D(nextX, nextY);
applyNodeDataToWindow(&nd);
mastersLeft--;
@ -443,8 +443,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
nextX += WIDTH;
}
} else { // orientation left, right or center
float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WSSIZE.x;
float heightLeft = WSSIZE.y;
float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WORKAREA.w;
float heightLeft = WORKAREA.h;
int mastersLeft = MASTERS;
float nextX = 0;
float nextY = 0;
@ -452,11 +452,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
if (STACKWINDOWS > 0 || centerMasterWindow)
WIDTH *= PMASTERNODE->percMaster;
if (orientation == ORIENTATION_RIGHT) {
nextX = WSSIZE.x - WIDTH;
} else if (centerMasterWindow) {
nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WSSIZE.x) - WIDTH) / 2;
}
if (orientation == ORIENTATION_RIGHT)
nextX = WORKAREA.w - WIDTH;
else if (centerMasterWindow)
nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WORKAREA.w) - WIDTH) / 2;
for (auto& nd : m_masterNodesData) {
if (nd.workspaceID != pWorkspace->m_id || !nd.isMaster)
@ -467,12 +466,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
HEIGHT = heightLeft * 0.9f;
if (*PSMARTRESIZING) {
nd.percSize *= WSSIZE.y / masterAccumulatedSize;
nd.percSize *= WORKAREA.h / masterAccumulatedSize;
HEIGHT = masterAverageSize * nd.percSize;
}
nd.size = Vector2D(WIDTH, HEIGHT);
nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_position : WSPOS) + Vector2D(nextX, nextY);
nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_position : WORKAREA.pos()) + Vector2D(nextX, nextY);
applyNodeDataToWindow(&nd);
mastersLeft--;
@ -487,8 +486,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
// compute placement of slave window(s)
int slavesLeft = STACKWINDOWS;
if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
const float HEIGHT = WSSIZE.y - PMASTERNODE->size.y;
float widthLeft = WSSIZE.x;
const float HEIGHT = WORKAREA.h - PMASTERNODE->size.y;
float widthLeft = WORKAREA.w;
float nextX = 0;
float nextY = 0;
@ -504,12 +503,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
WIDTH = widthLeft * 0.9f;
if (*PSMARTRESIZING) {
nd.percSize *= WSSIZE.x / slaveAccumulatedSize;
nd.percSize *= WORKAREA.w / slaveAccumulatedSize;
WIDTH = slaveAverageSize * nd.percSize;
}
nd.size = Vector2D(WIDTH, HEIGHT);
nd.position = WSPOS + Vector2D(nextX, nextY);
nd.position = WORKAREA.pos() + Vector2D(nextX, nextY);
applyNodeDataToWindow(&nd);
slavesLeft--;
@ -517,8 +516,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
nextX += WIDTH;
}
} else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) {
const float WIDTH = WSSIZE.x - PMASTERNODE->size.x;
float heightLeft = WSSIZE.y;
const float WIDTH = WORKAREA.w - PMASTERNODE->size.x;
float heightLeft = WORKAREA.h;
float nextY = 0;
float nextX = 0;
@ -534,12 +533,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
HEIGHT = heightLeft * 0.9f;
if (*PSMARTRESIZING) {
nd.percSize *= WSSIZE.y / slaveAccumulatedSize;
nd.percSize *= WORKAREA.h / slaveAccumulatedSize;
HEIGHT = slaveAverageSize * nd.percSize;
}
nd.size = Vector2D(WIDTH, HEIGHT);
nd.position = WSPOS + Vector2D(nextX, nextY);
nd.position = WORKAREA.pos() + Vector2D(nextX, nextY);
applyNodeDataToWindow(&nd);
slavesLeft--;
@ -547,10 +546,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
nextY += HEIGHT;
}
} else { // slaves for centered master window(s)
const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->m_size.x : WSSIZE.x) - PMASTERNODE->size.x) / 2.0;
const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->m_size.x : WORKAREA.w) - PMASTERNODE->size.x) / 2.0;
float heightLeft = 0;
float heightLeftL = WSSIZE.y;
float heightLeftR = WSSIZE.y;
float heightLeftL = WORKAREA.h;
float heightLeftR = WORKAREA.h;
float nextX = 0;
float nextY = 0;
float nextYL = 0;
@ -564,8 +563,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
slavesLeftL = slavesLeft - slavesLeftR;
}
const float slaveAverageHeightL = WSSIZE.y / slavesLeftL;
const float slaveAverageHeightR = WSSIZE.y / slavesLeftR;
const float slaveAverageHeightL = WORKAREA.h / slavesLeftL;
const float slaveAverageHeightR = WORKAREA.h / slavesLeftR;
float slaveAccumulatedHeightL = 0;
float slaveAccumulatedHeightR = 0;
@ -590,7 +589,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
continue;
if (onRight) {
nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->m_reservedTopLeft.x : 0);
nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->m_reservedArea.left() : 0);
nextY = nextYR;
heightLeft = heightLeftR;
slavesLeft = slavesLeftR;
@ -607,16 +606,16 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
if (*PSMARTRESIZING) {
if (onRight) {
nd.percSize *= WSSIZE.y / slaveAccumulatedHeightR;
nd.percSize *= WORKAREA.h / slaveAccumulatedHeightR;
HEIGHT = slaveAverageHeightR * nd.percSize;
} else {
nd.percSize *= WSSIZE.y / slaveAccumulatedHeightL;
nd.percSize *= WORKAREA.h / slaveAccumulatedHeightL;
HEIGHT = slaveAverageHeightL * nd.percSize;
}
}
nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->m_reservedBottomRight.x : PMONITOR->m_reservedTopLeft.x)) : WIDTH, HEIGHT);
nd.position = WSPOS + Vector2D(nextX, nextY);
nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->m_reservedArea.right() : PMONITOR->m_reservedArea.left())) : WIDTH, HEIGHT);
nd.position = WORKAREA.pos() + Vector2D(nextX, nextY);
applyNodeDataToWindow(&nd);
if (onRight) {
@ -637,6 +636,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
PHLMONITOR PMONITOR = nullptr;
const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID);
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
for (auto const& m : g_pCompositor->m_monitors) {
if (m->activeSpecialWorkspaceID() == pNode->workspaceID) {
@ -644,19 +645,20 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
break;
}
}
} else
PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_monitor.lock();
} else if (WS)
PMONITOR = WS->m_monitor.lock();
if (!PMONITOR) {
if (!PMONITOR || !WS) {
Debug::log(ERR, "Orphaned Node {}!!", pNode);
return;
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y);
const auto WORKAREA = workAreaOnWorkspace(WS);
const bool DISPLAYLEFT = STICKS(pNode->position.x, WORKAREA.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, WORKAREA.x + WORKAREA.w);
const bool DISPLAYTOP = STICKS(pNode->position.y, WORKAREA.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, WORKAREA.y + WORKAREA.h);
const auto PWINDOW = pNode->pWindow.lock();
// get specific gaps and rules for this workspace,
@ -669,14 +671,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
PWINDOW->updateWindowData();
static auto PANIMATE = CConfigValue<Hyprlang::INT>("misc:animate_manual_resizes");
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
auto* PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
auto* PGAPSOUT = sc<CCssGapData*>((PGAPSOUTDATA.ptr())->getData());
static auto PANIMATE = CConfigValue<Hyprlang::INT>("misc:animate_manual_resizes");
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
auto* PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
if (!validMapped(PWINDOW)) {
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
@ -691,9 +690,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
auto calcPos = PWINDOW->m_position;
auto calcSize = PWINDOW->m_size;
const auto OFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? gapsOut.m_left : gapsIn.m_left), sc<double>(DISPLAYTOP ? gapsOut.m_top : gapsIn.m_top));
const auto OFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? 0 : gapsIn.m_left), sc<double>(DISPLAYTOP ? 0 : gapsIn.m_top));
const auto OFFSETBOTTOMRIGHT = Vector2D(sc<double>(DISPLAYRIGHT ? gapsOut.m_right : gapsIn.m_right), sc<double>(DISPLAYBOTTOM ? gapsOut.m_bottom : gapsIn.m_bottom));
const auto OFFSETBOTTOMRIGHT = Vector2D(sc<double>(DISPLAYRIGHT ? 0 : gapsIn.m_right), sc<double>(DISPLAYBOTTOM ? 0 : gapsIn.m_bottom));
calcPos = calcPos + OFFSETTOPLEFT;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
@ -708,20 +707,17 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
if (*PCLAMP_TILED) {
const auto borderSize = PWINDOW->getRealBorderSize();
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
Vector2D monitorAvailable = WORKAREA.size() - Vector2D{2.0 * borderSize, 2.0 * borderSize};
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} :
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
calcSize = calcSize.clamp(minSize, maxSize);
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} :
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
calcSize = calcSize.clamp(minSize, maxSize);
calcPos += (availableSpace - calcSize) / 2.0;
calcPos.x = std::clamp(calcPos.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x + gapsOut.m_left + borderSize,
PMONITOR->m_size.x + PMONITOR->m_position.x - PMONITOR->m_reservedBottomRight.x - gapsOut.m_right - calcSize.x - borderSize);
calcPos.y = std::clamp(calcPos.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y + gapsOut.m_top + borderSize,
PMONITOR->m_size.y + PMONITOR->m_position.y - PMONITOR->m_reservedBottomRight.y - gapsOut.m_bottom - calcSize.y - borderSize);
calcPos.x = std::clamp(calcPos.x, WORKAREA.x + borderSize, WORKAREA.x + WORKAREA.w - calcSize.x - borderSize);
calcPos.y = std::clamp(calcPos.y, WORKAREA.y + borderSize, WORKAREA.y + WORKAREA.h - calcSize.y - borderSize);
}
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
@ -776,10 +772,11 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
static auto SLAVECOUNTFORCENTER = CConfigValue<Hyprlang::INT>("master:slave_count_for_center_master");
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x);
const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y);
const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x);
const auto WORKAREA = PMONITOR->logicalBoxMinusReserved();
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, WORKAREA.y + WORKAREA.h);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, WORKAREA.x + WORKAREA.w);
const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, WORKAREA.y);
const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, WORKAREA.x);
const bool LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT;
const bool TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT;
@ -825,13 +822,12 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
const bool isStackVertical = orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || orientation == ORIENTATION_CENTER;
const auto RESIZEDELTA = isStackVertical ? pixResize.y : pixResize.x;
const auto WSSIZE = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight;
auto nodesInSameColumn = PNODE->isMaster ? MASTERS : STACKWINDOWS;
if (orientation == ORIENTATION_CENTER && !PNODE->isMaster)
nodesInSameColumn = DISPLAYRIGHT ? (nodesInSameColumn + 1) / 2 : nodesInSameColumn / 2;
const auto SIZE = isStackVertical ? WSSIZE.y / nodesInSameColumn : WSSIZE.x / nodesInSameColumn;
const auto SIZE = isStackVertical ? WORKAREA.h / nodesInSameColumn : WORKAREA.w / nodesInSameColumn;
if (RESIZEDELTA != 0 && nodesInSameColumn > 1) {
if (!*PSMARTRESIZING) {
@ -840,7 +836,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
const auto NODEIT = std::ranges::find(m_masterNodesData, *PNODE);
const auto REVNODEIT = std::ranges::find(m_masterNodesData | std::views::reverse, *PNODE);
const float totalSize = isStackVertical ? WSSIZE.y : WSSIZE.x;
const float totalSize = isStackVertical ? WORKAREA.h : WORKAREA.w;
const float minSize = totalSize / nodesInSameColumn * 0.2;
const bool resizePrevNodes = isStackVertical ? (TOP || DISPLAYBOTTOM) && !DISPLAYTOP : (LEFT || DISPLAYRIGHT) && !DISPLAYLEFT;
@ -936,9 +932,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
// To keep consistent with the settings without C+P code
SMasterNodeData fakeNode;
const auto WORKAREA = PMONITOR->logicalBoxMinusReserved();
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->m_position + PMONITOR->m_reservedTopLeft;
fakeNode.size = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight;
fakeNode.position = WORKAREA.pos();
fakeNode.size = WORKAREA.size();
fakeNode.workspaceID = pWindow->workspaceID();
pWindow->m_position = fakeNode.position;
pWindow->m_size = fakeNode.size;