File 0.49.0.patch of Package hyprland-plugins

From c491d2831448645f24a1597a17f564aa52691ac6 Mon Sep 17 00:00:00 2001
From: Constantin Piber <59023762+cpiber@users.noreply.github.com>
Date: Fri, 9 May 2025 18:09:02 +0200
Subject: [PATCH 1/6] trails: Chase hyprland (#338)

CShader -> SShader https://github.com/hyprwm/Hyprland/commit/22b12e3013adf66b462b174688f82bd53ba8e721
---
 hyprtrails/globals.hpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hyprtrails/globals.hpp b/hyprtrails/globals.hpp
index f5d8802..5abe391 100644
--- a/hyprtrails/globals.hpp
+++ b/hyprtrails/globals.hpp
@@ -5,8 +5,8 @@
 inline HANDLE PHANDLE = nullptr;
 
 struct SGlobalState {
-    CShader          trailShader;
+    SShader          trailShader;
     wl_event_source* tick = nullptr;
 };
 
-inline UP<SGlobalState> g_pGlobalState;
\ No newline at end of file
+inline UP<SGlobalState> g_pGlobalState;

From b8c75de20a99ad760ef395e3184d6f99c9fc367d Mon Sep 17 00:00:00 2001
From: Vaxry <vaxry@vaxry.net>
Date: Sat, 17 May 2025 15:08:30 +0200
Subject: [PATCH 2/6] hyprbars: add enabled config option

---
 hyprbars/README.md   |  2 ++
 hyprbars/barDeco.cpp | 16 ++++++++++++----
 hyprbars/barDeco.hpp | 27 ++++++++++++++-------------
 hyprbars/main.cpp    |  1 +
 4 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/hyprbars/README.md b/hyprbars/README.md
index daee7a0..d444f0a 100644
--- a/hyprbars/README.md
+++ b/hyprbars/README.md
@@ -22,6 +22,8 @@ plugin {
 }
 ```
 
+`enabled` -> (bool) whether to enable the bars
+
 `bar_color` -> (col) bar's background color
 
 `bar_height` -> (int) bar's height (default `15`)
diff --git a/hyprbars/barDeco.cpp b/hyprbars/barDeco.cpp
index 6c7d906..edde102 100644
--- a/hyprbars/barDeco.cpp
+++ b/hyprbars/barDeco.cpp
@@ -20,7 +20,7 @@ CHyprBar::CHyprBar(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow) {
     static auto* const PCOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_color")->getDataStaticPtr();
 
     const auto         PMONITOR = pWindow->m_monitor.lock();
-    PMONITOR->m_scheduledRecalc   = true;
+    PMONITOR->m_scheduledRecalc = true;
 
     //button events
     m_pMouseButtonCallback = HyprlandAPI::registerCallbackDynamic(
@@ -54,6 +54,7 @@ CHyprBar::~CHyprBar() {
 
 SDecorationPositioningInfo CHyprBar::getPositioningInfo() {
     static auto* const         PHEIGHT     = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_height")->getDataStaticPtr();
+    static auto* const         PENABLED    = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:enabled")->getDataStaticPtr();
     static auto* const         PPRECEDENCE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_precedence_over_border")->getDataStaticPtr();
 
     SDecorationPositioningInfo info;
@@ -61,7 +62,7 @@ SDecorationPositioningInfo CHyprBar::getPositioningInfo() {
     info.edges          = DECORATION_EDGE_TOP;
     info.priority       = **PPRECEDENCE ? 10005 : 5000;
     info.reserved       = true;
-    info.desiredExtents = {{0, m_hidden ? 0 : **PHEIGHT}, {0, 0}};
+    info.desiredExtents = {{0, m_hidden || !**PENABLED ? 0 : **PHEIGHT}, {0, 0}};
     return info;
 }
 
@@ -495,7 +496,14 @@ void CHyprBar::renderBarButtonsText(CBox* barBox, const float scale, const float
 }
 
 void CHyprBar::draw(PHLMONITOR pMonitor, const float& a) {
-    if (m_hidden || !validMapped(m_pWindow))
+    static auto* const PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:enabled")->getDataStaticPtr();
+
+    if (m_bLastEnabledState != **PENABLED) {
+        m_bLastEnabledState = **PENABLED;
+        g_pDecorationPositioner->repositionDeco(this);
+    }
+
+    if (m_hidden || !validMapped(m_pWindow) || !**PENABLED)
         return;
 
     const auto PWINDOW = m_pWindow.lock();
@@ -678,7 +686,7 @@ void CHyprBar::updateRules() {
 
     m_bForcedBarColor   = std::nullopt;
     m_bForcedTitleColor = std::nullopt;
-    m_hidden           = false;
+    m_hidden            = false;
 
     for (auto& r : rules) {
         applyRule(r);
diff --git a/hyprbars/barDeco.hpp b/hyprbars/barDeco.hpp
index 853f32a..4847f6e 100644
--- a/hyprbars/barDeco.hpp
+++ b/hyprbars/barDeco.hpp
@@ -57,9 +57,10 @@ class CHyprBar : public IHyprWindowDecoration {
     SP<CTexture>              m_pButtonsTex;
 
     bool                      m_bWindowSizeChanged = false;
-    bool                      m_hidden            = false;
+    bool                      m_hidden             = false;
     bool                      m_bTitleColorChanged = false;
     bool                      m_bButtonHovered     = false;
+    bool                      m_bLastEnabledState  = false;
     std::optional<CHyprColor> m_bForcedBarColor;
     std::optional<CHyprColor> m_bForcedTitleColor;
 
@@ -83,23 +84,23 @@ class CHyprBar : public IHyprWindowDecoration {
     void                      handleDownEvent(SCallbackInfo& info, std::optional<ITouch::SDownEvent> touchEvent);
     void                      handleUpEvent(SCallbackInfo& info);
     void                      handleMovement();
-    bool                      doButtonPress(Hyprlang::INT* const* PBARPADDING, Hyprlang::INT* const* PBARBUTTONPADDING, Hyprlang::INT* const* PHEIGHT, Vector2D COORDS, bool BUTTONSRIGHT);
+    bool doButtonPress(Hyprlang::INT* const* PBARPADDING, Hyprlang::INT* const* PBARBUTTONPADDING, Hyprlang::INT* const* PHEIGHT, Vector2D COORDS, bool BUTTONSRIGHT);
 
-    CBox                      assignedBoxGlobal();
+    CBox assignedBoxGlobal();
 
-    SP<HOOK_CALLBACK_FN>      m_pMouseButtonCallback;
-    SP<HOOK_CALLBACK_FN>      m_pTouchDownCallback;
-    SP<HOOK_CALLBACK_FN>      m_pTouchUpCallback;
+    SP<HOOK_CALLBACK_FN> m_pMouseButtonCallback;
+    SP<HOOK_CALLBACK_FN> m_pTouchDownCallback;
+    SP<HOOK_CALLBACK_FN> m_pTouchUpCallback;
 
-    SP<HOOK_CALLBACK_FN>      m_pTouchMoveCallback;
-    SP<HOOK_CALLBACK_FN>      m_pMouseMoveCallback;
+    SP<HOOK_CALLBACK_FN> m_pTouchMoveCallback;
+    SP<HOOK_CALLBACK_FN> m_pMouseMoveCallback;
 
-    std::string               m_szLastTitle;
+    std::string          m_szLastTitle;
 
-    bool                      m_bDraggingThis  = false;
-    bool                      m_bTouchEv       = false;
-    bool                      m_bDragPending   = false;
-    bool                      m_bCancelledDown = false;
+    bool                 m_bDraggingThis  = false;
+    bool                 m_bTouchEv       = false;
+    bool                 m_bDragPending   = false;
+    bool                 m_bCancelledDown = false;
 
     // store hover state for buttons as a bitfield
     unsigned int m_iButtonHoverState = 0;
diff --git a/hyprbars/main.cpp b/hyprbars/main.cpp
index 4b280fb..df34ad0 100644
--- a/hyprbars/main.cpp
+++ b/hyprbars/main.cpp
@@ -140,6 +140,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
     HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment", Hyprlang::STRING{"right"});
     HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_padding", Hyprlang::INT{7});
     HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding", Hyprlang::INT{5});
+    HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:enabled", Hyprlang::INT{1});
     HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:icon_on_hover", Hyprlang::INT{0});
 
     HyprlandAPI::addConfigKeyword(PHANDLE, "hyprbars-button", onNewButton, Hyprlang::SHandlerOptions{});

From 803343f7efc6d668e7b2d8424e6852014bdd1731 Mon Sep 17 00:00:00 2001
From: Vaxry <vaxry@vaxry.net>
Date: Sun, 18 May 2025 18:14:46 +0200
Subject: [PATCH 3/6] hyprscrolling: fix reserved area

fixes #346
---
 hyprscrolling/Scrolling.cpp | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/hyprscrolling/Scrolling.cpp b/hyprscrolling/Scrolling.cpp
index bb89ffe..7891578 100644
--- a/hyprscrolling/Scrolling.cpp
+++ b/hyprscrolling/Scrolling.cpp
@@ -129,16 +129,19 @@ void SWorkspaceData::recalculate() {
 
     const auto MAX_WIDTH = maxWidth();
 
-    PHLMONITOR PMONITOR    = workspace->m_monitor.lock();
-    double     currentLeft = MAX_WIDTH < PMONITOR->m_size.x ? std::round((PMONITOR->m_size.x - MAX_WIDTH) / 2.0) : leftOffset; // layout pixels
+    PHLMONITOR PMONITOR = workspace->m_monitor.lock();
+
+    const CBox USABLE = CBox{PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight};
+
+    double     currentLeft = MAX_WIDTH < USABLE.w ? std::round((USABLE.w - MAX_WIDTH) / 2.0) : leftOffset; // layout pixels
 
     for (const auto& COL : columns) {
         double       currentTop  = 0.0;
-        const double ITEM_HEIGHT = PMONITOR->m_size.y / COL->windowDatas.size();
-        const double ITEM_WIDTH  = *PFSONONE && columns.size() == 1 ? PMONITOR->m_size.x : PMONITOR->m_size.x * COL->columnWidth;
+        const double ITEM_HEIGHT = USABLE.h / COL->windowDatas.size();
+        const double ITEM_WIDTH  = *PFSONONE && columns.size() == 1 ? USABLE.w : USABLE.w * COL->columnWidth;
 
         for (const auto& WINDOW : COL->windowDatas) {
-            WINDOW->layoutBox = CBox{currentLeft, currentTop, ITEM_WIDTH, ITEM_HEIGHT}.translate(PMONITOR->m_position);
+            WINDOW->layoutBox = CBox{currentLeft, currentTop, ITEM_WIDTH, ITEM_HEIGHT}.translate(PMONITOR->m_position + PMONITOR->m_reservedTopLeft);
 
             currentTop += ITEM_HEIGHT;
 

From 05dae996ebbed14c6476b83a7d014d00754febd2 Mon Sep 17 00:00:00 2001
From: Vaxry <vaxry@vaxry.net>
Date: Sun, 18 May 2025 19:03:07 +0200
Subject: [PATCH 4/6] hyprscroller: add mouse resize controls

fixes #347
---
 hyprscrolling/Scrolling.cpp | 166 +++++++++++++++++++++++++++++++++---
 hyprscrolling/Scrolling.hpp |  12 ++-
 2 files changed, 164 insertions(+), 14 deletions(-)

diff --git a/hyprscrolling/Scrolling.cpp b/hyprscrolling/Scrolling.cpp
index 7891578..a973382 100644
--- a/hyprscrolling/Scrolling.cpp
+++ b/hyprscrolling/Scrolling.cpp
@@ -5,17 +5,46 @@
 #include <hyprland/src/config/ConfigValue.hpp>
 #include <hyprland/src/render/Renderer.hpp>
 
+constexpr float MIN_COLUMN_WIDTH = 0.05F;
+constexpr float MAX_COLUMN_WIDTH = 1.F;
+constexpr float MIN_ROW_HEIGHT   = 0.1F;
+constexpr float MAX_ROW_HEIGHT   = 1.F;
+
+//
 void SColumnData::add(PHLWINDOW w) {
-    windowDatas.emplace_back(makeShared<SScrollingWindowData>(w, self.lock()));
+    for (auto& wd : windowDatas) {
+        wd->windowSize *= (float)windowDatas.size() / (float)(windowDatas.size() + 1);
+    }
+
+    windowDatas.emplace_back(makeShared<SScrollingWindowData>(w, self.lock(), 1.F / (float)(windowDatas.size() + 1)));
 }
 
 void SColumnData::add(SP<SScrollingWindowData> w) {
+    for (auto& wd : windowDatas) {
+        wd->windowSize *= (float)windowDatas.size() / (float)(windowDatas.size() + 1);
+    }
+
     windowDatas.emplace_back(w);
-    w->column = self;
+    w->column     = self;
+    w->windowSize = 1.F / (float)(windowDatas.size() + 1);
 }
 
 void SColumnData::remove(PHLWINDOW w) {
+    const auto SIZE_BEFORE = windowDatas.size();
     std::erase_if(windowDatas, [&w](const auto& e) { return e->window == w; });
+
+    if (SIZE_BEFORE == windowDatas.size() && SIZE_BEFORE > 0)
+        return;
+
+    float newMaxSize = 0.F;
+    for (auto& wd : windowDatas) {
+        newMaxSize += wd->windowSize;
+    }
+
+    for (auto& wd : windowDatas) {
+        wd->windowSize *= 1.F / newMaxSize;
+    }
+
     if (windowDatas.empty() && workspace)
         workspace->remove(self.lock());
 }
@@ -38,6 +67,28 @@ void SColumnData::down(SP<SScrollingWindowData> w) {
     }
 }
 
+SP<SScrollingWindowData> SColumnData::next(SP<SScrollingWindowData> w) {
+    for (size_t i = 0; i < windowDatas.size() - 1; ++i) {
+        if (windowDatas[i] != w)
+            continue;
+
+        return windowDatas[i + 1];
+    }
+
+    return nullptr;
+}
+
+SP<SScrollingWindowData> SColumnData::prev(SP<SScrollingWindowData> w) {
+    for (size_t i = 1; i < windowDatas.size(); ++i) {
+        if (windowDatas[i] != w)
+            continue;
+
+        return windowDatas[i - 1];
+    }
+
+    return nullptr;
+}
+
 SP<SColumnData> SWorkspaceData::add() {
     static const auto PCOLWIDTH = CConfigValue<Hyprlang::FLOAT>("plugin:hyprscrolling:column_width");
     auto              col       = columns.emplace_back(makeShared<SColumnData>(self.lock()));
@@ -131,19 +182,18 @@ void SWorkspaceData::recalculate() {
 
     PHLMONITOR PMONITOR = workspace->m_monitor.lock();
 
-    const CBox USABLE = CBox{PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight};
+    const CBox USABLE = layout->usableAreaFor(PMONITOR);
 
     double     currentLeft = MAX_WIDTH < USABLE.w ? std::round((USABLE.w - MAX_WIDTH) / 2.0) : leftOffset; // layout pixels
 
     for (const auto& COL : columns) {
-        double       currentTop  = 0.0;
-        const double ITEM_HEIGHT = USABLE.h / COL->windowDatas.size();
-        const double ITEM_WIDTH  = *PFSONONE && columns.size() == 1 ? USABLE.w : USABLE.w * COL->columnWidth;
+        double       currentTop = 0.0;
+        const double ITEM_WIDTH = *PFSONONE && columns.size() == 1 ? USABLE.w : USABLE.w * COL->columnWidth;
 
         for (const auto& WINDOW : COL->windowDatas) {
-            WINDOW->layoutBox = CBox{currentLeft, currentTop, ITEM_WIDTH, ITEM_HEIGHT}.translate(PMONITOR->m_position + PMONITOR->m_reservedTopLeft);
+            WINDOW->layoutBox = CBox{currentLeft, currentTop, ITEM_WIDTH, WINDOW->windowSize * USABLE.h}.translate(PMONITOR->m_position + PMONITOR->m_reservedTopLeft);
 
-            currentTop += ITEM_HEIGHT;
+            currentTop += WINDOW->windowSize * USABLE.h;
 
             layout->applyNodeDataToWindow(WINDOW, false);
         }
@@ -376,8 +426,98 @@ void CScrollingLayout::onBeginDragWindow() {
     IHyprLayout::onBeginDragWindow();
 }
 
-void CScrollingLayout::resizeActiveWindow(const Vector2D&, eRectCorner corner, PHLWINDOW pWindow) {
-    ;
+void CScrollingLayout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, PHLWINDOW pWindow) {
+    const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_lastWindow.lock();
+
+    if (!validMapped(PWINDOW))
+        return;
+
+    const auto DATA = dataFor(PWINDOW);
+
+    if (!DATA) {
+        *PWINDOW->m_realSize =
+            (PWINDOW->m_realSize->goal() + delta)
+                .clamp(PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
+        PWINDOW->updateWindowDecos();
+        return;
+    }
+
+    if (corner == CORNER_NONE)
+        return;
+
+    if (!DATA->column || !DATA->column->workspace || !DATA->column->workspace->workspace || !DATA->column->workspace->workspace->m_monitor)
+        return;
+
+    const auto USABLE        = usableAreaFor(DATA->column->workspace->workspace->m_monitor.lock());
+    const auto DELTA_AS_PERC = delta / USABLE.size();
+
+    const auto CURR_COLUMN = DATA->column.lock();
+    const auto NEXT_COLUMN = DATA->column->workspace->next(CURR_COLUMN);
+    const auto PREV_COLUMN = DATA->column->workspace->prev(CURR_COLUMN);
+
+    switch (corner) {
+        case CORNER_BOTTOMLEFT:
+        case CORNER_TOPLEFT: {
+            if (!PREV_COLUMN)
+                break;
+
+            PREV_COLUMN->columnWidth = std::clamp(PREV_COLUMN->columnWidth + (float)DELTA_AS_PERC.x, MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH);
+            CURR_COLUMN->columnWidth = std::clamp(CURR_COLUMN->columnWidth - (float)DELTA_AS_PERC.x, MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH);
+            break;
+        }
+        case CORNER_BOTTOMRIGHT:
+        case CORNER_TOPRIGHT: {
+            if (!NEXT_COLUMN)
+                break;
+
+            NEXT_COLUMN->columnWidth = std::clamp(NEXT_COLUMN->columnWidth - (float)DELTA_AS_PERC.x, MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH);
+            CURR_COLUMN->columnWidth = std::clamp(CURR_COLUMN->columnWidth + (float)DELTA_AS_PERC.x, MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH);
+            break;
+        }
+
+        default: break;
+    }
+
+    if (DATA->column->windowDatas.size() > 1) {
+        const auto CURR_WD = DATA;
+        const auto NEXT_WD = DATA->column->next(DATA);
+        const auto PREV_WD = DATA->column->prev(DATA);
+
+        switch (corner) {
+            case CORNER_BOTTOMLEFT:
+            case CORNER_BOTTOMRIGHT: {
+                if (!NEXT_WD)
+                    break;
+
+                if (NEXT_WD->windowSize <= MIN_ROW_HEIGHT && delta.y >= 0)
+                    break;
+
+                float adjust = std::clamp((float)(delta.y / USABLE.h), (-CURR_WD->windowSize + MIN_ROW_HEIGHT), (NEXT_WD->windowSize - MIN_ROW_HEIGHT));
+
+                NEXT_WD->windowSize = std::clamp(NEXT_WD->windowSize - adjust, MIN_ROW_HEIGHT, MAX_ROW_HEIGHT);
+                CURR_WD->windowSize = std::clamp(CURR_WD->windowSize + adjust, MIN_ROW_HEIGHT, MAX_ROW_HEIGHT);
+                break;
+            }
+            case CORNER_TOPLEFT:
+            case CORNER_TOPRIGHT: {
+                if (!PREV_WD)
+                    break;
+
+                if (PREV_WD->windowSize <= MIN_ROW_HEIGHT && delta.y <= 0 || CURR_WD->windowSize <= MIN_ROW_HEIGHT && delta.y >= 0)
+                    break;
+
+                float adjust = std::clamp((float)(delta.y / USABLE.h), -(PREV_WD->windowSize - MIN_ROW_HEIGHT), (CURR_WD->windowSize - MIN_ROW_HEIGHT));
+
+                PREV_WD->windowSize = std::clamp(PREV_WD->windowSize + adjust, MIN_ROW_HEIGHT, MAX_ROW_HEIGHT);
+                CURR_WD->windowSize = std::clamp(CURR_WD->windowSize - adjust, MIN_ROW_HEIGHT, MAX_ROW_HEIGHT);
+                break;
+            }
+
+            default: break;
+        }
+    }
+
+    DATA->column->workspace->recalculate();
 }
 
 void CScrollingLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) {
@@ -467,7 +607,7 @@ std::any CScrollingLayout::layoutMessage(SLayoutMessageHeader header, std::strin
             WDATA->column->columnWidth = abs;
         }
 
-        WDATA->column->columnWidth = std::clamp(WDATA->column->columnWidth, 0.05F, 1.F);
+        WDATA->column->columnWidth = std::clamp(WDATA->column->columnWidth, MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH);
 
         WDATA->column->workspace->recalculate();
     } else if (ARGS[0] == "movewindowto") {
@@ -576,3 +716,7 @@ SP<SWorkspaceData> CScrollingLayout::currentWorkspaceData() {
 
     return dataFor(g_pCompositor->m_lastMonitor->m_activeWorkspace);
 }
+
+CBox CScrollingLayout::usableAreaFor(PHLMONITOR m) {
+    return CBox{m->m_reservedTopLeft, m->m_size - m->m_reservedTopLeft - m->m_reservedBottomRight};
+}
diff --git a/hyprscrolling/Scrolling.hpp b/hyprscrolling/Scrolling.hpp
index 94ffda8..3e1ff68 100644
--- a/hyprscrolling/Scrolling.hpp
+++ b/hyprscrolling/Scrolling.hpp
@@ -9,12 +9,13 @@ struct SColumnData;
 struct SWorkspaceData;
 
 struct SScrollingWindowData {
-    SScrollingWindowData(PHLWINDOW w, SP<SColumnData> col) : window(w), column(col) {
+    SScrollingWindowData(PHLWINDOW w, SP<SColumnData> col, float ws = 1.F) : window(w), column(col), windowSize(ws) {
         ;
     }
 
     PHLWINDOWREF    window;
     WP<SColumnData> column;
+    float           windowSize = 1.F;
 
     CBox            layoutBox;
 };
@@ -28,8 +29,11 @@ struct SColumnData {
     void                                  add(SP<SScrollingWindowData> w);
     void                                  remove(PHLWINDOW w);
 
-    void up(SP<SScrollingWindowData> w);
-    void down(SP<SScrollingWindowData> w);
+    void                                  up(SP<SScrollingWindowData> w);
+    void                                  down(SP<SScrollingWindowData> w);
+
+    SP<SScrollingWindowData>              next(SP<SScrollingWindowData> w);
+    SP<SScrollingWindowData>              prev(SP<SScrollingWindowData> w);
 
     std::vector<SP<SScrollingWindowData>> windowDatas;
     float                                 columnSize  = 1.F;
@@ -85,6 +89,8 @@ class CScrollingLayout : public IHyprLayout {
     virtual void                     onEnable();
     virtual void                     onDisable();
 
+    CBox                             usableAreaFor(PHLMONITOR m);
+
   private:
     std::vector<SP<SWorkspaceData>> m_workspaceDatas;
 

From f7665af8500b442ebe37cf23d4fc3def5b941812 Mon Sep 17 00:00:00 2001
From: Vaxry <vaxry@vaxry.net>
Date: Sun, 18 May 2025 20:57:19 +0200
Subject: [PATCH 5/6] hyprscrolling: fixup minor oopsie

fixes #349
---
 hyprscrolling/Scrolling.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hyprscrolling/Scrolling.cpp b/hyprscrolling/Scrolling.cpp
index a973382..8f111d6 100644
--- a/hyprscrolling/Scrolling.cpp
+++ b/hyprscrolling/Scrolling.cpp
@@ -26,7 +26,7 @@ void SColumnData::add(SP<SScrollingWindowData> w) {
 
     windowDatas.emplace_back(w);
     w->column     = self;
-    w->windowSize = 1.F / (float)(windowDatas.size() + 1);
+    w->windowSize = 1.F / (float)(windowDatas.size());
 }
 
 void SColumnData::remove(PHLWINDOW w) {

From 4dea1029e837ae642979ab509eb2eddc959470d0 Mon Sep 17 00:00:00 2001
From: Vaxry <vaxry@vaxry.net>
Date: Sun, 18 May 2025 21:18:38 +0200
Subject: [PATCH 6/6] hyprscrolling: add preconfigured widths for resize

ref #348
---
 hyprscrolling/README.md     |  3 ++-
 hyprscrolling/Scrolling.cpp | 48 +++++++++++++++++++++++++++++++++++++
 hyprscrolling/Scrolling.hpp | 15 ++++++++----
 hyprscrolling/main.cpp      |  1 +
 4 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/hyprscrolling/README.md b/hyprscrolling/README.md
index f6a5cf1..6e6a928 100644
--- a/hyprscrolling/README.md
+++ b/hyprscrolling/README.md
@@ -12,6 +12,7 @@ Adds a scrolling layout to Hyprland.
 | -- | -- | -- | -- |
 | fullscreen_on_one_column | if there's only one column, should it be fullscreen | bool | false |
 | column_width | default column width as a fraction of the monitor width | float [0 - 1] | 0.5 |
+| explicit_column_widths | a comma-separated list of widths for columns to be used with `+conf` or `-conf` | string | `0.333, 0.5, 0.667, 1.0` |
 
 
 ## Layout messages
@@ -19,5 +20,5 @@ Adds a scrolling layout to Hyprland.
 | name | description | params |
 | --- | --- | --- |
 | move | move the layout horizontally, by either a relative logical px (`-200`, `+200`) or columns (`+col`, `-col`) | move data |
-| colresize | resize the current column, to either a value or by a relative value e.g. `0.5`, `+0.2`, `-0.2` | relative float |
+| colresize | resize the current column, to either a value or by a relative value e.g. `0.5`, `+0.2`, `-0.2` or cycle the preconfigured ones with `+conf` or `-conf` | relative float / relative conf |
 | movewindowto | same as the movewindow dispatcher but supports promotion to the right at the end | direction |
\ No newline at end of file
diff --git a/hyprscrolling/Scrolling.cpp b/hyprscrolling/Scrolling.cpp
index 8f111d6..b5f1a08 100644
--- a/hyprscrolling/Scrolling.cpp
+++ b/hyprscrolling/Scrolling.cpp
@@ -5,6 +5,9 @@
 #include <hyprland/src/config/ConfigValue.hpp>
 #include <hyprland/src/render/Renderer.hpp>
 
+#include <hyprutils/string/ConstVarList.hpp>
+using namespace Hyprutils::String;
+
 constexpr float MIN_COLUMN_WIDTH = 0.05F;
 constexpr float MAX_COLUMN_WIDTH = 1.F;
 constexpr float MIN_ROW_HEIGHT   = 0.1F;
@@ -336,6 +339,20 @@ void CScrollingLayout::applyNodeDataToWindow(SP<SScrollingWindowData> data, bool
 }
 
 void CScrollingLayout::onEnable() {
+    static const auto PCONFWIDTHS = CConfigValue<Hyprlang::STRING>("plugin:hyprscrolling:explicit_column_widths");
+
+    m_configCallback = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
+        // bitch ass
+        m_config.configuredWidths.clear();
+
+        CConstVarList widths(*PCONFWIDTHS, 0, ',');
+        for (auto& w : widths) {
+            try {
+                m_config.configuredWidths.emplace_back(std::stof(std::string{w}));
+            } catch (...) { Debug::log(ERR, "scrolling: Failed to parse width {} as float", w); }
+        }
+    });
+
     for (auto const& w : g_pCompositor->m_windows) {
         if (w->m_isFloating || !w->m_isMapped || w->isHidden())
             continue;
@@ -346,6 +363,7 @@ void CScrollingLayout::onEnable() {
 
 void CScrollingLayout::onDisable() {
     m_workspaceDatas.clear();
+    m_configCallback.reset();
 }
 
 void CScrollingLayout::onWindowCreatedTiling(PHLWINDOW window, eDirection direction) {
@@ -592,6 +610,36 @@ std::any CScrollingLayout::layoutMessage(SLayoutMessageHeader header, std::strin
             return {};
 
         if (ARGS[1][0] == '+' || ARGS[1][0] == '-') {
+            if (ARGS[1] == "+conf") {
+                for (size_t i = 0; i < m_config.configuredWidths.size(); ++i) {
+                    if (m_config.configuredWidths[i] < WDATA->column->columnWidth)
+                        continue;
+
+                    if (i == m_config.configuredWidths.size() - 1)
+                        WDATA->column->columnWidth = m_config.configuredWidths[0];
+                    else
+                        WDATA->column->columnWidth = m_config.configuredWidths[i + 1];
+
+                    break;
+                }
+
+                return {};
+            } else if (ARGS[1] == "-conf") {
+                for (size_t i = m_config.configuredWidths.size() - 1; i >= 0; --i) {
+                    if (m_config.configuredWidths[i] > WDATA->column->columnWidth)
+                        continue;
+
+                    if (i == 0)
+                        WDATA->column->columnWidth = m_config.configuredWidths[m_config.configuredWidths.size() - 1];
+                    else
+                        WDATA->column->columnWidth = m_config.configuredWidths[i - 1];
+
+                    break;
+                }
+
+                return {};
+            }
+
             const auto PLUSMINUS = getPlusMinusKeywordResult(ARGS[1], 0);
 
             if (!PLUSMINUS.has_value())
diff --git a/hyprscrolling/Scrolling.hpp b/hyprscrolling/Scrolling.hpp
index 3e1ff68..a14238d 100644
--- a/hyprscrolling/Scrolling.hpp
+++ b/hyprscrolling/Scrolling.hpp
@@ -3,6 +3,7 @@
 #include <vector>
 #include <hyprland/src/layout/IHyprLayout.hpp>
 #include <hyprland/src/helpers/memory/Memory.hpp>
+#include <hyprland/src/managers/HookSystemManager.hpp>
 
 class CScrollingLayout;
 struct SColumnData;
@@ -94,11 +95,17 @@ class CScrollingLayout : public IHyprLayout {
   private:
     std::vector<SP<SWorkspaceData>> m_workspaceDatas;
 
-    SP<SWorkspaceData>              dataFor(PHLWORKSPACE ws);
-    SP<SScrollingWindowData>        dataFor(PHLWINDOW w);
-    SP<SWorkspaceData>              currentWorkspaceData();
+    SP<HOOK_CALLBACK_FN>            m_configCallback;
 
-    void                            applyNodeDataToWindow(SP<SScrollingWindowData> node, bool force);
+    struct {
+        std::vector<float> configuredWidths;
+    } m_config;
+
+    SP<SWorkspaceData>       dataFor(PHLWORKSPACE ws);
+    SP<SScrollingWindowData> dataFor(PHLWINDOW w);
+    SP<SWorkspaceData>       currentWorkspaceData();
+
+    void                     applyNodeDataToWindow(SP<SScrollingWindowData> node, bool force);
 
     friend struct SWorkspaceData;
 };
\ No newline at end of file
diff --git a/hyprscrolling/main.cpp b/hyprscrolling/main.cpp
index 6ef6f41..2e23d89 100644
--- a/hyprscrolling/main.cpp
+++ b/hyprscrolling/main.cpp
@@ -45,6 +45,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
 
     HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprscrolling:fullscreen_on_one_column", Hyprlang::INT{0});
     HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprscrolling:column_width", Hyprlang::FLOAT{0.5F});
+    HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprscrolling:explicit_column_widths", Hyprlang::STRING{"0.333, 0.5, 0.667, 1.0"});
     HyprlandAPI::addLayout(PHANDLE, "scrolling", g_pScrollingLayout.get());
 
         if (success) HyprlandAPI::addNotification(PHANDLE, "[hyprscrolling] Initialized successfully!", CHyprColor{0.2, 1.0, 0.2, 1.0}, 5000);
openSUSE Build Service is sponsored by