From fcd9d77b642c0cd45cae61cf10ed1924f2e7945b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 29 Mar 2024 00:43:50 +0000 Subject: [PATCH] layout: improve initial size prediction for floating --- src/events/Windows.cpp | 17 +---------- src/layout/DwindleLayout.cpp | 2 +- src/layout/DwindleLayout.hpp | 2 +- src/layout/IHyprLayout.cpp | 57 ++++++++++++++++++++++++++++++++++-- src/layout/IHyprLayout.hpp | 8 ++++- src/layout/MasterLayout.cpp | 2 +- src/layout/MasterLayout.hpp | 2 +- 7 files changed, 67 insertions(+), 23 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 0d1665b7..00546550 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -782,22 +782,7 @@ void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) { - Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(); - - if (g_pXWaylandManager->shouldBeFloated(PWINDOW, true)) - predSize = {}; - - Vector2D maxSize = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->pending.max_width, PWINDOW->m_uSurface.xdg->toplevel->pending.max_height}; - - if ((maxSize.x > 0 && maxSize.x < predSize.x) || (maxSize.y > 0 && maxSize.y < predSize.y)) - predSize = {}; - - for (auto& r : g_pConfigManager->getMatchingRules(PWINDOW, true, true)) { - if (r.szRule.starts_with("float")) { - predSize = {}; - break; - } - } + Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(PWINDOW); Debug::log(LOG, "Layout predicts size {} for {}", predSize, PWINDOW); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c34f04cc..fe8847ed 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -1116,7 +1116,7 @@ void CHyprDwindleLayout::onDisable() { m_lDwindleNodesData.clear(); } -Vector2D CHyprDwindleLayout::predictSizeForNewWindow() { +Vector2D CHyprDwindleLayout::predictSizeForNewWindowTiled() { if (!g_pCompositor->m_pLastMonitor) return {}; diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 5ca90fcd..b8c752f4 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -59,7 +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 Vector2D predictSizeForNewWindowTiled(); virtual void onEnable(); virtual void onDisable(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 6a32144e..1570fd73 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -644,8 +644,61 @@ void IHyprLayout::requestFocusForWindow(CWindow* pWindow) { g_pCompositor->warpCursorTo(pWindow->middle()); } -Vector2D IHyprLayout::predictSizeForNewWindow() { - return Vector2D{}; +Vector2D IHyprLayout::predictSizeForNewWindowFloating(CWindow* pWindow) { // get all rules, see if we have any size overrides. + Vector2D sizeOverride = {}; + if (g_pCompositor->m_pLastMonitor) { + for (auto& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { + if (r.szRule.starts_with("size")) { + try { + const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); + const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); + const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); + + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + + const auto SIZEX = SIZEXSTR == "max" ? + std::clamp(MAXSIZE.x, 20.0, g_pCompositor->m_pLastMonitor->vecSize.x) : + (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * g_pCompositor->m_pLastMonitor->vecSize.x); + const auto SIZEY = SIZEYSTR == "max" ? + std::clamp(MAXSIZE.y, 20.0, g_pCompositor->m_pLastMonitor->vecSize.y) : + (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * g_pCompositor->m_pLastMonitor->vecSize.y); + + sizeOverride = {SIZEX, SIZEY}; + + } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } + break; + } + } + } + + return sizeOverride; +} + +Vector2D IHyprLayout::predictSizeForNewWindow(CWindow* pWindow) { + bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true); + + if (!shouldBeFloated) { + for (auto& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { + if (r.szRule.starts_with("float")) { + shouldBeFloated = true; + break; + } + } + } + + Vector2D sizePredicted = {}; + + if (!shouldBeFloated) + sizePredicted = predictSizeForNewWindowTiled(); + else + sizePredicted = predictSizeForNewWindowFloating(pWindow); + + Vector2D maxSize = Vector2D{pWindow->m_uSurface.xdg->toplevel->pending.max_width, pWindow->m_uSurface.xdg->toplevel->pending.max_height}; + + if ((maxSize.x > 0 && maxSize.x < sizePredicted.x) || (maxSize.y > 0 && maxSize.y < sizePredicted.y)) + sizePredicted = {}; + + return sizePredicted; } IHyprLayout::~IHyprLayout() {} diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index e168556e..d6c41d3b 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -187,7 +187,13 @@ class IHyprLayout { Called to predict the size of a newly opened window to send it a configure. Return 0,0 if unpredictable */ - virtual Vector2D predictSizeForNewWindow(); + virtual Vector2D predictSizeForNewWindowTiled() = 0; + + /* + Prefer not overriding, use predictSizeForNewWindowTiled. + */ + virtual Vector2D predictSizeForNewWindow(CWindow* pWindow); + virtual Vector2D predictSizeForNewWindowFloating(CWindow* pWindow); private: int m_iMouseMoveEventCount; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 1c6be8d6..ea54b0e2 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1435,7 +1435,7 @@ void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) { applyNodeDataToWindow(PNODE); } -Vector2D CHyprMasterLayout::predictSizeForNewWindow() { +Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { static auto PNEWISMASTER = CConfigValue("master:new_is_master"); if (!g_pCompositor->m_pLastMonitor) diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 6f8ea120..1e48b5dd 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -65,7 +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 Vector2D predictSizeForNewWindowTiled(); virtual void onEnable(); virtual void onDisable();