mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-07 23:25:57 +01:00
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
This commit is contained in:
parent
0d53401217
commit
19bbdeed47
2 changed files with 166 additions and 13 deletions
|
@ -179,6 +179,7 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["master:orientation"].strValue = "left";
|
configValues["master:orientation"].strValue = "left";
|
||||||
configValues["master:inherit_fullscreen"].intValue = 1;
|
configValues["master:inherit_fullscreen"].intValue = 1;
|
||||||
configValues["master:allow_small_split"].intValue = 0;
|
configValues["master:allow_small_split"].intValue = 0;
|
||||||
|
configValues["master:smart_resizing"].intValue = 1;
|
||||||
|
|
||||||
configValues["animations:enabled"].intValue = 1;
|
configValues["animations:enabled"].intValue = 1;
|
||||||
|
|
||||||
|
|
|
@ -278,6 +278,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
eOrientation orientation = PWORKSPACEDATA->orientation;
|
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||||
bool centerMasterWindow = false;
|
bool centerMasterWindow = false;
|
||||||
static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue;
|
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 MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID);
|
||||||
const auto WINDOWS = getNodesOnWorkspace(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)
|
// compute placement of master window(s)
|
||||||
if (WINDOWS == 1 && !centerMasterWindow) {
|
if (WINDOWS == 1 && !centerMasterWindow) {
|
||||||
PMASTERNODE->size = WSSIZE;
|
PMASTERNODE->size = WSSIZE;
|
||||||
|
@ -318,6 +338,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
if (WIDTH > widthLeft * 0.9f && mastersLeft > 1)
|
if (WIDTH > widthLeft * 0.9f && mastersLeft > 1)
|
||||||
WIDTH = widthLeft * 0.9f;
|
WIDTH = widthLeft * 0.9f;
|
||||||
|
|
||||||
|
if (*PSMARTRESIZING) {
|
||||||
|
nd.percSize *= WSSIZE.x / masterAccumulatedSize;
|
||||||
|
WIDTH = masterAverageSize * nd.percSize;
|
||||||
|
}
|
||||||
|
|
||||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||||
applyNodeDataToWindow(&nd);
|
applyNodeDataToWindow(&nd);
|
||||||
|
@ -350,6 +375,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1)
|
if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1)
|
||||||
HEIGHT = heightLeft * 0.9f;
|
HEIGHT = heightLeft * 0.9f;
|
||||||
|
|
||||||
|
if (*PSMARTRESIZING) {
|
||||||
|
nd.percSize *= WSSIZE.y / masterAccumulatedSize;
|
||||||
|
HEIGHT = masterAverageSize * nd.percSize;
|
||||||
|
}
|
||||||
|
|
||||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||||
applyNodeDataToWindow(&nd);
|
applyNodeDataToWindow(&nd);
|
||||||
|
@ -382,6 +412,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
|
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
|
||||||
WIDTH = widthLeft * 0.9f;
|
WIDTH = widthLeft * 0.9f;
|
||||||
|
|
||||||
|
if (*PSMARTRESIZING) {
|
||||||
|
nd.percSize *= WSSIZE.x / slaveAccumulatedSize;
|
||||||
|
WIDTH = slaveAverageSize * nd.percSize;
|
||||||
|
}
|
||||||
|
|
||||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||||
applyNodeDataToWindow(&nd);
|
applyNodeDataToWindow(&nd);
|
||||||
|
@ -407,6 +442,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
||||||
HEIGHT = heightLeft * 0.9f;
|
HEIGHT = heightLeft * 0.9f;
|
||||||
|
|
||||||
|
if (*PSMARTRESIZING) {
|
||||||
|
nd.percSize *= WSSIZE.y / slaveAccumulatedSize;
|
||||||
|
HEIGHT = slaveAverageSize * nd.percSize;
|
||||||
|
}
|
||||||
|
|
||||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||||
applyNodeDataToWindow(&nd);
|
applyNodeDataToWindow(&nd);
|
||||||
|
@ -429,6 +469,25 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
int slavesLeftR = 1 + (slavesLeft - 1) / 2;
|
int slavesLeftR = 1 + (slavesLeft - 1) / 2;
|
||||||
int slavesLeftL = slavesLeft - slavesLeftR;
|
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) {
|
for (auto& nd : m_lMasterNodesData) {
|
||||||
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
||||||
continue;
|
continue;
|
||||||
|
@ -449,6 +508,16 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||||
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
||||||
HEIGHT = heightLeft * 0.9f;
|
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.size = Vector2D(WIDTH, HEIGHT);
|
||||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||||
applyNodeDataToWindow(&nd);
|
applyNodeDataToWindow(&nd);
|
||||||
|
@ -599,11 +668,20 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace);
|
const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace);
|
||||||
static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue;
|
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;
|
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||||
bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1);
|
bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1);
|
||||||
double delta = 0;
|
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)
|
if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 && !centered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -626,6 +704,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||||
// check the up/down resize
|
// check the up/down resize
|
||||||
const auto RESIZEDELTA = PWORKSPACEDATA->orientation % 2 == 1 ? pixResize.x : pixResize.y;
|
const auto RESIZEDELTA = PWORKSPACEDATA->orientation % 2 == 1 ? pixResize.x : pixResize.y;
|
||||||
|
|
||||||
|
if (!*PSMARTRESIZING) {
|
||||||
if (RESIZEDELTA != 0) {
|
if (RESIZEDELTA != 0) {
|
||||||
if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) {
|
if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) {
|
||||||
// check master size
|
// check master size
|
||||||
|
@ -641,6 +720,79 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||||
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
recalculateMonitor(PMONITOR->ID);
|
recalculateMonitor(PMONITOR->ID);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue