diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 81c5c800..d6241fa4 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -806,7 +806,9 @@ void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) { - wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, 0, 0); + const auto PREDSIZE = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(); + Debug::log(LOG, "Layout predicts size {} for {}", PREDSIZE, PWINDOW); + wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, PREDSIZE.x, PREDSIZE.y); return; } diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 0f4a5f87..2bb6e4c3 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -127,7 +127,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for const auto PWINDOW = pNode->pWindow; // get specific gaps and rules for this workspace, // if user specified them in config - const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(pNode->workspaceID)); + + if (!g_pCompositor->windowExists(PWINDOW)) { + Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); + onWindowRemovedTiling(PWINDOW); + return; + } if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) return; @@ -143,13 +149,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); - if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) { - Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); - onWindowRemovedTiling(PWINDOW); - return; - } - - CBox nodeBox = pNode->box; + CBox nodeBox = pNode->box; nodeBox.round(); PWINDOW->m_vSize = nodeBox.size(); @@ -1093,3 +1093,53 @@ void CHyprDwindleLayout::onEnable() { void CHyprDwindleLayout::onDisable() { m_lDwindleNodesData.clear(); } + +Vector2D CHyprDwindleLayout::predictSizeForNewWindow() { + if (!g_pCompositor->m_pLastMonitor) + return {}; + + // get window candidate + CWindow* candidate = g_pCompositor->m_pLastWindow; + + if (!candidate) + candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + + // create a fake node + SDwindleNodeData node; + + if (!candidate) + return g_pCompositor->m_pLastMonitor->vecSize; + else { + const auto PNODE = getNodeFromWindow(candidate); + + if (!PNODE) + return {}; + + node = *PNODE; + node.pWindow = nullptr; + + CBox box = PNODE->box; + + static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split"); + static auto* const PPRESERVESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:preserve_split"); + static auto* const PFLMULT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier"); + + bool splitTop = false; + + if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0) + splitTop = box.h * **PFLMULT > box.w; + + const auto SPLITSIDE = !splitTop; + + if (SPLITSIDE) + node.box = {{}, {box.w / 2.0, box.h}}; + else + node.box = {{}, {box.w, box.h / 2.0}}; + + // TODO: make this better and more accurate + + return node.box.size(); + } + + return {}; +} diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index f5501b28..fc73540a 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -59,6 +59,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual void alterSplitRatio(CWindow*, float, bool); virtual std::string getLayoutName(); virtual void replaceWindowDataWith(CWindow* from, CWindow* to); + virtual Vector2D predictSizeForNewWindow(); virtual void onEnable(); virtual void onDisable(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 49e20435..16474056 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -593,4 +593,8 @@ void IHyprLayout::requestFocusForWindow(CWindow* pWindow) { g_pCompositor->focusWindow(pWindow); } +Vector2D IHyprLayout::predictSizeForNewWindow() { + return Vector2D{}; +} + IHyprLayout::~IHyprLayout() {} diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 5c74078e..ffe004bc 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -181,6 +181,12 @@ class IHyprLayout { */ virtual void requestFocusForWindow(CWindow*); + /* + Called to predict the size of a newly opened window to send it a configure. + Return 0,0 if unpredictable + */ + virtual Vector2D predictSizeForNewWindow(); + private: Vector2D m_vBeginDragXY; Vector2D m_vLastDragXY; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 6a3cd492..1a488b0d 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1459,6 +1459,33 @@ void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) { applyNodeDataToWindow(PNODE); } +Vector2D CHyprMasterLayout::predictSizeForNewWindow() { + static auto* const PNEWISMASTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:new_is_master"); + + if (!g_pCompositor->m_pLastMonitor) + return {}; + + const int NODES = getNodesOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + + if (NODES <= 0) + return g_pCompositor->m_pLastMonitor->vecSize; + + const auto MASTER = getMasterNodeOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + if (!MASTER) // wtf + return {}; + + if (*PNEWISMASTER) { + return MASTER->size; + } else { + const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace); + + // TODO: make this better + return {g_pCompositor->m_pLastMonitor->vecSize.x - MASTER->size.x, g_pCompositor->m_pLastMonitor->vecSize.y / (SLAVES + 1)}; + } + + return {}; +} + void CHyprMasterLayout::onEnable() { for (auto& w : g_pCompositor->m_vWindows) { if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index e316556a..d48aefdc 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -65,6 +65,7 @@ class CHyprMasterLayout : public IHyprLayout { virtual void alterSplitRatio(CWindow*, float, bool); virtual std::string getLayoutName(); virtual void replaceWindowDataWith(CWindow* from, CWindow* to); + virtual Vector2D predictSizeForNewWindow(); virtual void onEnable(); virtual void onDisable();