diff options
author | Jeremy Huang <[email protected]> | 2023-09-10 14:58:06 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2023-09-10 22:58:06 +0100 |
commit | 19bbdeed47cdf4423e745a201137c96d74beb8a6 (patch) | |
tree | cd8835dc165e74c1536abebe1aafe4bc1f7fd95b | |
parent | 0d53401217b79a9dd552f84ce5d3f8b2985641ee (diff) | |
download | Hyprland-19bbdeed47cdf4423e745a201137c96d74beb8a6.tar.gz Hyprland-19bbdeed47cdf4423e745a201137c96d74beb8a6.zip |
master: Add smart resizing option for master layout (#3210)
* add smart resizing for master layout
* fix smart resizing workspace check
* master layout fix smart resize when at max size
* change resizing for center orientation so it doesnt use all nodes
* master layout resizing, simplify code for calculating total height and weight
* remove the redundant smart resizing check
-rw-r--r-- | src/config/ConfigManager.cpp | 1 | ||||
-rw-r--r-- | src/layout/MasterLayout.cpp | 178 |
2 files changed, 166 insertions, 13 deletions
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c8e2aa12..02a745fb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -179,6 +179,7 @@ void CConfigManager::setDefaultVars() { configValues["master:orientation"].strValue = "left"; configValues["master:inherit_fullscreen"].intValue = 1; configValues["master:allow_small_split"].intValue = 0; + configValues["master:smart_resizing"].intValue = 1; configValues["animations:enabled"].intValue = 1; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 42e2175c..d9116467 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -278,6 +278,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { eOrientation orientation = PWORKSPACEDATA->orientation; bool centerMasterWindow = false; static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; + static auto* const PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("master:smart_resizing")->intValue; const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); @@ -293,6 +294,25 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { } } + const float totalSize = (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) ? WSSIZE.x : WSSIZE.y; + const float masterAverageSize = totalSize / MASTERS; + const float slaveAverageSize = totalSize / STACKWINDOWS; + float masterAccumulatedSize = 0; + float slaveAccumulatedSize = 0; + + if (*PSMARTRESIZING) { + // check the total width and height so that later + // if larger/smaller than screen size them down/up + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID == PWORKSPACE->m_iID) { + if (nd.isMaster) + masterAccumulatedSize += totalSize / MASTERS * nd.percSize; + else + slaveAccumulatedSize += totalSize / STACKWINDOWS * nd.percSize; + } + } + } + // compute placement of master window(s) if (WINDOWS == 1 && !centerMasterWindow) { PMASTERNODE->size = WSSIZE; @@ -318,6 +338,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (WIDTH > widthLeft * 0.9f && mastersLeft > 1) WIDTH = widthLeft * 0.9f; + if (*PSMARTRESIZING) { + nd.percSize *= WSSIZE.x / masterAccumulatedSize; + WIDTH = masterAverageSize * nd.percSize; + } + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -350,6 +375,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1) HEIGHT = heightLeft * 0.9f; + if (*PSMARTRESIZING) { + nd.percSize *= WSSIZE.y / masterAccumulatedSize; + HEIGHT = masterAverageSize * nd.percSize; + } + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -382,6 +412,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (WIDTH > widthLeft * 0.9f && slavesLeft > 1) WIDTH = widthLeft * 0.9f; + if (*PSMARTRESIZING) { + nd.percSize *= WSSIZE.x / slaveAccumulatedSize; + WIDTH = slaveAverageSize * nd.percSize; + } + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -407,6 +442,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; + if (*PSMARTRESIZING) { + nd.percSize *= WSSIZE.y / slaveAccumulatedSize; + HEIGHT = slaveAverageSize * nd.percSize; + } + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -429,6 +469,25 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { int slavesLeftR = 1 + (slavesLeft - 1) / 2; int slavesLeftL = slavesLeft - slavesLeftR; + const float slaveAverageHeightL = WSSIZE.y / slavesLeftL; + const float slaveAverageHeightR = WSSIZE.y / slavesLeftR; + float slaveAccumulatedHeightL = 0; + float slaveAccumulatedHeightR = 0; + if (*PSMARTRESIZING) { + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) + continue; + + if (onRight) { + slaveAccumulatedHeightR += slaveAverageHeightR * nd.percSize; + } else { + slaveAccumulatedHeightL += slaveAverageHeightL * nd.percSize; + } + onRight = !onRight; + } + onRight = true; + } + for (auto& nd : m_lMasterNodesData) { if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) continue; @@ -449,6 +508,16 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; + if (*PSMARTRESIZING) { + if (onRight) { + nd.percSize *= WSSIZE.y / slaveAccumulatedHeightR; + HEIGHT = slaveAverageHeightR * nd.percSize; + } else { + nd.percSize *= WSSIZE.y / slaveAccumulatedHeightL; + HEIGHT = slaveAverageHeightL * nd.percSize; + } + } + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -599,11 +668,20 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; + static auto* const PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("master:smart_resizing")->intValue; eOrientation orientation = PWORKSPACEDATA->orientation; bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1); double delta = 0; + const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); + const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); + const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); + const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); + + const bool LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT; + const bool TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT; + if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 && !centered) return; @@ -626,19 +704,93 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne // check the up/down resize const auto RESIZEDELTA = PWORKSPACEDATA->orientation % 2 == 1 ? pixResize.x : pixResize.y; - if (RESIZEDELTA != 0) { - if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) { - // check master size - const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ? - (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / getMastersOnWorkspace(PNODE->workspaceID) : - (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID); - PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); - } else if (!PNODE->isMaster && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) > 1) { - const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ? (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / - (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) : - (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / - (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)); - PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); + if (!*PSMARTRESIZING) { + if (RESIZEDELTA != 0) { + if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) { + // check master size + const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ? + (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / getMastersOnWorkspace(PNODE->workspaceID) : + (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID); + PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); + } else if (!PNODE->isMaster && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) > 1) { + const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ? (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / + (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) : + (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / + (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)); + PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); + } + } + } else { + const auto MASTERS = getMastersOnWorkspace(PNODE->workspaceID); + const auto WINDOWS = getNodesOnWorkspace(PNODE->workspaceID); + const auto STACKWINDOWS = WINDOWS - MASTERS; + const auto WSSIZE = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + + const bool isStackVertical = orientation % 2 == 0; + auto nodesInSameColumn = PNODE->isMaster ? MASTERS : STACKWINDOWS; + if (orientation == ORIENTATION_CENTER && !PNODE->isMaster) + nodesInSameColumn /= 2; + + if (RESIZEDELTA != 0 && nodesInSameColumn > 1) { + const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); + const auto REVNODEIT = std::find(m_lMasterNodesData.rbegin(), m_lMasterNodesData.rend(), *PNODE); + const auto SIZE = isStackVertical ? + (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / nodesInSameColumn: + (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / nodesInSameColumn; + + const float totalSize = isStackVertical ? WSSIZE.y : WSSIZE.x; + const float minSize = totalSize / nodesInSameColumn * 0.2; + const bool resizePrevNodes = isStackVertical ? (TOP || DISPLAYBOTTOM) && !DISPLAYTOP : (LEFT || DISPLAYRIGHT) && !DISPLAYLEFT; + + int nodesLeft = 0; + float sizeLeft = 0; + int nodeCount = 0; + // check the sizes of all the nodes to be resized for later calculation + auto checkNodesLeft = [&sizeLeft, &nodesLeft, orientation, isStackVertical, &nodeCount, PNODE](auto it) { + if (it.isMaster != PNODE->isMaster || it.workspaceID != PNODE->workspaceID) + return; + nodeCount++; + if (!it.isMaster && orientation == ORIENTATION_CENTER && nodeCount % 2 == 1) + return; + sizeLeft += isStackVertical ? it.size.y : it.size.x; + nodesLeft++; + }; + float resizeDiff; + if (resizePrevNodes) { + std::for_each(std::next(REVNODEIT), m_lMasterNodesData.rend(), checkNodesLeft); + resizeDiff = -RESIZEDELTA; + } else { + std::for_each(std::next(NODEIT), m_lMasterNodesData.end(), checkNodesLeft); + resizeDiff = RESIZEDELTA; + } + + const float nodeSize = isStackVertical ? PNODE->size.y : PNODE->size.x; + const float maxSizeIncrease = sizeLeft - nodesLeft * minSize; + const float maxSizeDecrease = minSize - nodeSize; + + // leaves enough room for the other nodes + resizeDiff = std::clamp(resizeDiff, maxSizeDecrease, maxSizeIncrease); + PNODE->percSize += resizeDiff / SIZE; + + // resize the other nodes + nodeCount = 0; + auto resizeNodesLeft = [maxSizeIncrease, resizeDiff, minSize, orientation, isStackVertical, SIZE, &nodeCount, nodesLeft, PNODE](auto &it) { + if (it.isMaster != PNODE->isMaster || it.workspaceID != PNODE->workspaceID) + return; + nodeCount++; + // if center orientation, only resize when on the same side + if (!it.isMaster && orientation == ORIENTATION_CENTER && nodeCount % 2 == 1) + return; + const float size = isStackVertical ? it.size.y : it.size.x; + const float resizeDeltaForEach = maxSizeIncrease != 0 ? + resizeDiff * (size - minSize) / maxSizeIncrease : resizeDiff / nodesLeft; + it.percSize -= resizeDeltaForEach / SIZE; + }; + if (resizePrevNodes) { + std::for_each(std::next(REVNODEIT), m_lMasterNodesData.rend(), resizeNodesLeft); + } else { + std::for_each(std::next(NODEIT), m_lMasterNodesData.end(), resizeNodesLeft); + } } } |