From 7be897d6ae765fab756c0b7e6b91e8c5b39a419e Mon Sep 17 00:00:00 2001 From: Ralph Zhou <36948728+awerty-noob@users.noreply.github.com> Date: Mon, 6 Oct 2025 19:00:49 +0800 Subject: [PATCH] Hyprscrolling: (feat) Add `togglefit` command (#498) * Hyprscrolling: (feat) Add `togglefit` command * fix multi-workspaces bugs and focus change bug. * fix center to fitcol bug * remove "fullyvisible" logic to simplify the logic --- hyprscrolling/README.md | 1 + hyprscrolling/Scrolling.cpp | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/hyprscrolling/README.md b/hyprscrolling/README.md index a8ca531..31c8338 100644 --- a/hyprscrolling/README.md +++ b/hyprscrolling/README.md @@ -39,6 +39,7 @@ plugin { | promote | moves a window to its own new column | none | | swapcol | Swaps the current column with its neighbor to the left (`l`) or right (`r`). The swap wraps around (e.g., swapping the first column left moves it to the end). | `l` or `r` | | movecoltoworkspace | Moves the entire current column to the specified workspace, preserving its internal layout. Works with existing, new, and special workspaces. e.g. like `1`, `2`, `-1`, `+2`, `special`, etc. | workspace identifier| +| togglefit | Toggle the focus_fit_method (center, fit) | none | Example key bindings for your Hyprland config: ``` diff --git a/hyprscrolling/Scrolling.cpp b/hyprscrolling/Scrolling.cpp index 39e6717..98d3fad 100644 --- a/hyprscrolling/Scrolling.cpp +++ b/hyprscrolling/Scrolling.cpp @@ -1344,6 +1344,66 @@ std::any CScrollingLayout::layoutMessage(SLayoutMessageHeader header, std::strin g_pCompositor->focusWindow(windowsToMove.front()); g_pCompositor->warpCursorTo(windowsToMove.front()->middle()); + } else if (ARGS[0] == "togglefit") { + static const auto PFITMETHOD = CConfigValue("plugin:hyprscrolling:focus_fit_method"); + auto& fitMethod = *PFITMETHOD.ptr(); + const int toggled = fitMethod ^ 1; + + fitMethod = toggled; + + const auto focusedData = dataFor(g_pCompositor->m_lastWindow.lock()); + static const auto PFSONONE = CConfigValue("plugin:hyprscrolling:fullscreen_on_one_column"); + + for (const auto& ws : m_workspaceDatas) { + if (!ws || ws->columns.empty()) + continue; + + const auto monitor = ws->workspace->m_monitor.lock(); + if (!monitor) + continue; + + const auto USABLE = usableAreaFor(monitor); + + const auto focusedColumn = (focusedData && focusedData->column && focusedData->column->workspace.lock() == ws) ? focusedData->column.lock() : nullptr; + + const auto fallbackColumn = ws->atCenter(); + + if (toggled == 1) { + const auto columnToFit = focusedColumn ? focusedColumn : fallbackColumn; + if (!columnToFit) + continue; + + double currentLeft = 0.0; + for (const auto& col : ws->columns) { + const double itemWidth = *PFSONONE && ws->columns.size() == 1 ? USABLE.w : USABLE.w * col->columnWidth; + + if (col == columnToFit) { + const double colLeft = currentLeft; + const double colRight = currentLeft + itemWidth; + const double scrollMax = std::max(ws->maxWidth() - USABLE.w, 0.0); + double desiredOffset; + + if (col == ws->columns.front()) + desiredOffset = 0.0; + else + desiredOffset = std::clamp(colRight - USABLE.w, 0.0, scrollMax); + + ws->leftOffset = desiredOffset; + break; + } + + currentLeft += itemWidth; + } + } else { + const auto columnToCenter = focusedColumn ? focusedColumn : fallbackColumn; + if (!columnToCenter) + continue; + + ws->centerCol(columnToCenter); + } + + ws->recalculate(); + } } return {}; }