diff options
| author | erstarr <253168930+erstarr@users.noreply.github.com> | 2026-05-08 17:45:43 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-08 16:45:43 +0100 |
| commit | bd7f695363898826d5bd04fe830f19581ac4c5b2 (patch) | |
| tree | a4dd157b8d851330035b4b6184995fb4ebd9d277 /src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp | |
| parent | ac75bcab713490eb000e4fa48f7e7316c3535854 (diff) | |
algo/scrolling: various scrolling view related bugfixes (#13974)
* fix scrolling view move when a grouped window is closed - prevent redundant space assignment for a grouped window that's about to be unmapped, add a `FOCUS_REASON` for unmapping grouped windows
* fix focus_fallback after unmapping a window floating moving view
* fix view change when changing workspaces (special and normal).
add an optional `RECALCULATE_REASON` parameter to `recalculate()` calls of all algorithms.
add an optional `RECALCULATE_MONITOR_REASON` parameter to `recalculateMonitor()` calls.
add 2 new `FOCUS_REASON`s, for workspace change and special workspace toggle
* Fix hyprctl keyword causing scrolling view move.
rename INPUT_MODE_KB to INPUT_MODE_HARD since it seems to have little to do with keybinds
* fix fullscreen/maximise moving the scrolling view
* fix opening of layer 3 programs moving scrolling view
* refactor, clean up and clang-format
* fix bad decisions
* fix includes, clang-format.
* remove TODO
* `focuswindow` no longer moves scrolling view when `follow_focus = 0`
* fix: changes in a group's current window no longer casues scrolling view shift when `follow_focus = 0`
* fix: `moveintogroup`, `movewindoworgroup` no longer causes scrolling view change if `follow_focus = 0`
* clang-format
* add `RECALCULATE_REASON_UNKNOWN`, `RECALCULATE_MONITOR_REASON_UNKNOWN`, `REMOVE_FROM_GROUP_REASON_UNKNOWN`
remove optional wrapper from their enums, refactor code to work with the change
* dispatches that call `switchtoWindow()` in CKeybindManager no longer cause scrolling view to move if `follow_focus = 0`.
They still cause the move if `follow_focus = 1`
Dispatches effected by this: `movefocus`, `cyclenext`, `focuscurrentorlast`, `focuscurrentorurgent`
* Fix for Lua: switchToWondow
* Fix for Lua: focus({window})
* Fix for Lua: Move Window Into Group
* clang-format
* Drop `hyprctl keyword` change
* test: `focus({window})` with `follow_focus = false`
* test: `focus({window})` with `follow_focus = true`
* test: test Focus Fallback
* test: Focus Fallback with groups
* test: workspace change
* test: special workspace toggle
* test: workspace change - special to special
also minor refactoring
* test: close window in a group
* test: move window into group `follow_focus = false`
minor fix in test: expect -> assert
* test: move window into group `follow_focus = true`
* test: new layer
* test: maximise
fix in test: expect to assert.
* test: fullscreen
* test: `dispatch window.focus({ direction })` when `follow_focus = false`
* test: `dispatch window.focus({ direction })` when `follow_focus = true`
test-fix: expect -> assert
* test: move focus within group when `follow_focus = false`
* test: move focus within group when `follow_focus = true`
* test-fix: kill all layers before killing all windows in layers test. prevents internal post test cleanup function failing to kill all layers
test-fix: maximized and fullscreen swapped between their tests
test-fix: testScrollingViewBehaviourMoveFocusInGroupFollowFocusTrue missing layout initialization
test-fix: testScrollingViewBehaviourWorkspaceChange, testScrollingViewBehaviourCloseWindowInGroup have stale window class in a comment
clang-format
* catch up with main: move to new test function
* clean-up the clean-up part of the tests: redundant
* clang-format
* pain
* suffering: fix rebase fail
* test: manually kill all layers since the cleanup function fails
* remove test: fullscreen and maximise. scrolling has its own behaviour now
Diffstat (limited to 'src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp')
| -rw-r--r-- | src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp index 613ebe19..842e5b85 100644 --- a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp +++ b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp @@ -601,7 +601,16 @@ CScrollingAlgorithm::CScrollingAlgorithm() { if (!TARGET || TARGET->floating()) return; - focusOnInput(TARGET, reason == Desktop::FOCUS_REASON_CLICK ? INPUT_MODE_CLICK : (Desktop::isHardInputFocusReason(reason) ? INPUT_MODE_KB : INPUT_MODE_SOFT)); + // if follow_focus != 0, focuswindow always moves scrolling view + // if follow_focus != 0, change in a group's current window state always moves scrolling view + // if follow_focus != 0, moving a window into group via the corresponding dispatches `moveintogroup`, `movewindoworgroup` always moves scrolling view + // if follow_focus != 0, moving focus via dispatches that cause switching to a specific window via calling switchToWindow(), such as movefocus, cyclenext, focuscurrentor(last/urgent); always moves scrolling view + if (*PFOLLOW_FOCUS && + (reason == Desktop::FOCUS_REASON_DISPATCH_FOCUSWINDOW || reason == Desktop::FOCUS_REASON_GROUP_CURRENT_WINDOW_CHANGE || + reason == Desktop::FOCUS_REASON_DISPATCH_MOVEWINDOWINTOGROUP || reason == Desktop::FOCUS_REASON_SWITCH_TO_WINDOW_SOFT)) + focusOnInput(TARGET, INPUT_MODE_HARD); + else + focusOnInput(TARGET, reason == Desktop::FOCUS_REASON_CLICK ? INPUT_MODE_CLICK : (Desktop::isHardInputFocusReason(reason) ? INPUT_MODE_HARD : INPUT_MODE_SOFT)); }); // Initialize default widths and direction @@ -645,7 +654,7 @@ void CScrollingAlgorithm::focusOnInput(SP<ITarget> target, eInputMode input) { } // if we moved via non-kb, and it's fully visible, ignore - if (m_scrollingData->visible(TARGETDATA->column.lock(), true) && input != INPUT_MODE_KB) + if (m_scrollingData->visible(TARGETDATA->column.lock(), true) && input != INPUT_MODE_HARD) return; static const auto PFITMETHOD = CConfigValue<Config::INTEGER>("scrolling:focus_fit_method"); @@ -867,7 +876,7 @@ void CScrollingAlgorithm::resizeTarget(const Vector2D& delta, SP<ITarget> target m_scrollingData->recalculate(true); } -void CScrollingAlgorithm::recalculate() { +void CScrollingAlgorithm::recalculate(eRecalculateReason reason) { // guard against recalculation during transitional monitor states // (e.g. monitor reconnecting after suspend where workspace/monitor may not be ready) if (!m_parent || !m_parent->space() || !m_parent->space()->workspace() || !m_parent->space()->workspace()->m_monitor) @@ -878,8 +887,14 @@ void CScrollingAlgorithm::recalculate() { const auto TARGETDATA = dataFor(TARGET); - if (TARGETDATA && !m_scrollingData->visible(TARGETDATA->column.lock(), true)) - focusOnInput(Desktop::focusState()->window()->layoutTarget(), INPUT_MODE_KB); + if (TARGETDATA && !m_scrollingData->visible(TARGETDATA->column.lock(), true)) { + + /* guard against unwanted scrolling viewport moves - If recalculate() was called, it is assumed that either the INPUT_MODE will be HARD (i.e. it is meant to move the scrolling viewport) or + it is not meant to move the scrolling viewport. + (e.g. changing workspace to a scrolling layout workspace fits the focused window in that workspace into view) */ + if (Layout::isHardRecalculateReason(reason)) + focusOnInput(Desktop::focusState()->window()->layoutTarget(), INPUT_MODE_HARD); + } } m_scrollingData->recalculate(); |
