aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeremy Huang <[email protected]>2023-09-10 14:58:06 -0700
committerGitHub <[email protected]>2023-09-10 22:58:06 +0100
commit19bbdeed47cdf4423e745a201137c96d74beb8a6 (patch)
treecd8835dc165e74c1536abebe1aafe4bc1f7fd95b
parent0d53401217b79a9dd552f84ce5d3f8b2985641ee (diff)
downloadHyprland-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.cpp1
-rw-r--r--src/layout/MasterLayout.cpp178
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);
+ }
}
}