From 89f795da98cc53faf7e3a683d8c189aa24986267 Mon Sep 17 00:00:00 2001 From: memchr Date: Sat, 15 Jun 2024 19:17:38 +0000 Subject: [PATCH] master: refine master layout new window handling (#6479) * ## Open window relative to active window `new_on_active`: - `none` (default): - `before`: above of the focused window - `after`: below the focused window If the focused window is the solo master window, or the new window replaces master, this option has no effect and new_on_top are respected. ## Refine new window status control **BREAKING CHANGE**: new_is_master removed in favour of new variable `new_status`: - `slave` (default): new window open as slave - `master`: new window open as master - `inherit`: new window inherit status from active window, i.e. when the focused window is master, new window will become new master, otherwise new window are added to slaves * refactor: rename a few variables --- src/config/ConfigManager.cpp | 3 +- src/layout/MasterLayout.cpp | 54 +++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f63ff552..1b069f5d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -431,8 +431,9 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:special_scale_factor", {1.f}); m_pConfig->addConfigValue("master:mfact", {0.55f}); - m_pConfig->addConfigValue("master:new_is_master", Hyprlang::INT{1}); + m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:orientation", {"left"}); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index af0182e1..c5784c74 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -76,17 +76,31 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire if (pWindow->m_bIsFloating) return; - static auto PNEWTOP = CConfigValue("master:new_on_top"); + static auto PNEWONACTIVE = CConfigValue("master:new_on_active"); + static auto PNEWONTOP = CConfigValue("master:new_on_top"); + static auto PNEWSTATUS = CConfigValue("master:new_status"); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); + const bool BNEWBEFOREACTIVE = *PNEWONACTIVE == "before"; + const bool BNEWISMASTER = *PNEWSTATUS == "master"; + + const auto PNODE = [&]() { + if (*PNEWONACTIVE != "none" && !BNEWISMASTER) { + const auto pLastNode = getNodeFromWindow(g_pCompositor->m_pLastWindow.lock()); + if (pLastNode && !(pLastNode->isMaster && (getMastersOnWorkspace(pWindow->workspaceID()) == 1 || *PNEWSTATUS == "slave"))) { + auto it = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *pLastNode); + if (!BNEWBEFOREACTIVE) + ++it; + return &(*m_lMasterNodesData.emplace(it)); + } + } + return *PNEWONTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); + }(); PNODE->workspaceID = pWindow->workspaceID(); PNODE->pWindow = pWindow; - static auto PNEWISMASTER = CConfigValue("master:new_is_master"); - const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); static auto PMFACT = CConfigValue("master:mfact"); float lastSplitPercent = *PMFACT; @@ -186,13 +200,27 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire } } - if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) || - forceDropAsMaster) { - for (auto& nd : m_lMasterNodesData) { - if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { - nd.isMaster = false; - lastSplitPercent = nd.percMaster; - break; + if ((BNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) // + || WINDOWSONWORKSPACE == 1 // + || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) // + || forceDropAsMaster // + || (*PNEWSTATUS == "inherit" && OPENINGON && OPENINGON->isMaster && g_pInputManager->dragMode != MBIND_MOVE)) { + + if (BNEWBEFOREACTIVE) { + for (auto& nd : m_lMasterNodesData | std::views::reverse) { + if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + nd.isMaster = false; + lastSplitPercent = nd.percMaster; + break; + } + } + } else { + for (auto& nd : m_lMasterNodesData) { + if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + nd.isMaster = false; + lastSplitPercent = nd.percMaster; + break; + } } } @@ -1440,7 +1468,7 @@ void CHyprMasterLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) { } Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { - static auto PNEWISMASTER = CConfigValue("master:new_is_master"); + static auto PNEWSTATUS = CConfigValue("master:new_status"); if (!g_pCompositor->m_pLastMonitor) return {}; @@ -1454,7 +1482,7 @@ Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { if (!MASTER) // wtf return {}; - if (*PNEWISMASTER) { + if (*PNEWSTATUS == "master") { return MASTER->size; } else { const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);