From 33d06fb0e5033412638edec5a8d78cbec844132a Mon Sep 17 00:00:00 2001 From: Person1873 <87143469+Person1873@users.noreply.github.com> Date: Fri, 14 Apr 2023 00:20:58 +1000 Subject: [PATCH] Add ability to split master when only 1 additional window (#2025) * fix: enable master split less than 2 windows added a config flag "master:allow_small_split" added config to minimum windows check. TODO: check that no bug added (remove all masters?) * IMPL:FIX: multiple master windows full width Implemented the ability to have multiple master windows filling the full monitor width in master mode. this is controlled by the config option master:allow_small_split (true/false) this defaults to false as it was the original behaviour before this patch * BUGFIX: corrected issue with blanks re: addmaster FIX 1: Treat ORIENTATION_CENTER the same as ORIENTATION_LEFT unless there are enough STACK_WINDOWS to fill both wings. FIX 2: enforced last window always set as master in MasterLayout::CHyperMasterLayout::calculateWorkspace(); FIX 3: fix 2, also fixed focus issues previously noted. * Changes requested by vaxerski changed how we access config variables (by reference not value) fixed a regression previously missed prior to requested changes. I had somehow broken the very functionality i meant to add. * added static keyword to config variables * removed superfluous static tags I made a mistake with making too many variables static. this made them only evaluate once per runtime breaking things majorly. My appologies. I haven't touched C++ in nearly 20 years. * remove annoying comment --------- Co-authored-by: vaxerski <43317083+vaxerski@users.noreply.github.com> --- src/config/ConfigManager.cpp | 1 + src/layout/MasterLayout.cpp | 65 ++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c49114d2..b8dd3321 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -144,6 +144,7 @@ void CConfigManager::setDefaultVars() { configValues["master:no_gaps_when_only"].intValue = 0; configValues["master:orientation"].strValue = "left"; configValues["master:inherit_fullscreen"].intValue = 1; + configValues["master:allow_small_split"].intValue = 0; configValues["animations:enabled"].intValue = 1; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index eebe787e..b1322d4b 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -153,6 +153,10 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { if (!PNODE) return; + const auto WORKSPACEID = PNODE->workspaceID; + const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); + static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue; + pWindow->m_sSpecialRenderData.rounding = true; pWindow->m_sSpecialRenderData.border = true; pWindow->m_sSpecialRenderData.decorate = true; @@ -160,12 +164,10 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { if (pWindow->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); - const auto MASTERSLEFT = getMastersOnWorkspace(PNODE->workspaceID); - - if (PNODE->isMaster && MASTERSLEFT < 2) { - // find new one + if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) { + // find a new master from top of the list for (auto& nd : m_lMasterNodesData) { - if (!nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + if (!nd.isMaster && nd.workspaceID == WORKSPACEID) { nd.isMaster = true; nd.percMaster = PNODE->percMaster; break; @@ -173,8 +175,6 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { } } - const auto WORKSPACEID = PNODE->workspaceID; - m_lMasterNodesData.remove(*PNODE); if (getMastersOnWorkspace(WORKSPACEID) == getNodesOnWorkspace(WORKSPACEID) && MASTERSLEFT > 1) { @@ -185,7 +185,16 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { } } } - + // BUGFIX: correct bug where closing one master in a stack of 2 would leave + // the screen half bare, and make it difficult to select remaining window + if (getNodesOnWorkspace(WORKSPACEID) == 1) { + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID == WORKSPACEID && nd.isMaster == false) { + nd.isMaster = true; + break; + } + } + } recalculateMonitor(pWindow->m_iMonitorID); } @@ -254,20 +263,26 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { } } - const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); - + const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); + const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); + const auto STACKWINDOWS = WINDOWS - MASTERS; //compute placement of master window(s) - if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2 && !centerMasterWindow) { + if ((WINDOWS < 2) && !centerMasterWindow) { PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition; PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); applyNodeDataToWindow(PMASTERNODE); return; - } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) { - float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; - int nodesLeft = MASTERS; - float nextY = 0; - const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster; + } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { + float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; + int nodesLeft = MASTERS; + float nextY = 0; + float WIDTH = 0; + + if (STACKWINDOWS == 0 && MASTERS > 0) + WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x); + else + WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster; for (auto& n : m_lMasterNodesData) { if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { @@ -315,7 +330,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { applyNodeDataToWindow(&n); } } - } else if (orientation == ORIENTATION_CENTER) { + } else if (orientation == ORIENTATION_CENTER && STACKWINDOWS >= 2) { float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; int nodesLeft = MASTERS; float nextY = 0; @@ -341,7 +356,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { //compute placement of slave window(s) int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS; - if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) { + if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; float nextY = 0; const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x; @@ -350,7 +365,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) continue; - if (orientation == ORIENTATION_LEFT) { + if (orientation == ORIENTATION_LEFT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY); } else { @@ -392,7 +407,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { applyNodeDataToWindow(&nd); } - } else if (orientation == ORIENTATION_CENTER) { + } else if (orientation == ORIENTATION_CENTER && STACKWINDOWS >= 2) { float heightLeftL = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; float heightLeftR = heightLeftL; float heightLeft = 0; @@ -951,14 +966,14 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (header.pWindow->m_bIsFloating) return 0; - const auto PNODE = getNodeFromWindow(header.pWindow); + const auto PNODE = getNodeFromWindow(header.pWindow); - const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID); - const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID); + const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID); + const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID); + static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue; - if (MASTERS + 2 > WINDOWS) + if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0) return 0; - prepareLoseFocus(header.pWindow); if (!PNODE || PNODE->isMaster) {