From 8ccf0f53d407972f7a19b9bb6bf98172a511bd20 Mon Sep 17 00:00:00 2001 From: erstarr <253168930+erstarr@users.noreply.github.com> Date: Sat, 4 Apr 2026 04:09:20 +0200 Subject: [PATCH] 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 --- src/desktop/state/FocusState.hpp | 2 ++ src/helpers/Monitor.cpp | 14 ++++++------- src/layout/LayoutManager.cpp | 21 ++++++++++++++----- src/layout/LayoutManager.hpp | 9 ++++++-- src/layout/algorithm/Algorithm.cpp | 6 +++--- src/layout/algorithm/Algorithm.hpp | 5 +++-- src/layout/algorithm/FloatingAlgorithm.cpp | 2 +- src/layout/algorithm/FloatingAlgorithm.hpp | 2 +- src/layout/algorithm/ModeAlgorithm.hpp | 3 ++- .../tiled/dwindle/DwindleAlgorithm.cpp | 2 +- .../tiled/dwindle/DwindleAlgorithm.hpp | 2 +- .../tiled/master/MasterAlgorithm.cpp | 2 +- .../tiled/master/MasterAlgorithm.hpp | 2 +- .../tiled/monocle/MonocleAlgorithm.cpp | 2 +- .../tiled/monocle/MonocleAlgorithm.hpp | 4 ++-- .../tiled/scrolling/ScrollingAlgorithm.cpp | 9 +++++--- .../tiled/scrolling/ScrollingAlgorithm.hpp | 4 ++-- src/layout/space/Space.cpp | 4 ++-- src/layout/space/Space.hpp | 9 +++++++- 19 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/desktop/state/FocusState.hpp b/src/desktop/state/FocusState.hpp index f2e187fcf..b294c375b 100644 --- a/src/desktop/state/FocusState.hpp +++ b/src/desktop/state/FocusState.hpp @@ -13,6 +13,8 @@ namespace Desktop { FOCUS_REASON_CLICK, FOCUS_REASON_OTHER, FOCUS_REASON_DESKTOP_STATE_CHANGE, + FOCUS_REASON_WORKSPACE_CHANGE, + FOCUS_REASON_TOGGLE_SPECIAL_WORKSPACE, FOCUS_REASON_UNMAP_WINDOW_TILING, FOCUS_REASON_UNMAP_WINDOW_FLOATING, FOCUS_REASON_UNMAP_GROUPED_WINDOW, diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a5195a94f..fe75040ed 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1409,13 +1409,13 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo pWindow = pWorkspace->getFirstWindow(); } - Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND); + Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_WORKSPACE_CHANGE); } if (!noMouseMove) g_pInputManager->simulateMouseMovement(); - g_layoutManager->recalculateMonitor(m_self.lock()); + g_layoutManager->recalculateMonitor(m_self.lock(), Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_WORKSPACE_CHANGE); g_pEventManager->postEvent(SHyprIPCEvent{"workspace", pWorkspace->m_name}); g_pEventManager->postEvent(SHyprIPCEvent{"workspacev2", std::format("{},{}", pWorkspace->m_id, pWorkspace->m_name)}); @@ -1478,11 +1478,11 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (POLDSPECIAL) POLDSPECIAL->m_events.activeChanged.emit(); - g_layoutManager->recalculateMonitor(m_self.lock()); + g_layoutManager->recalculateMonitor(m_self.lock(), Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE); if (!(Desktop::focusState()->window() && Desktop::focusState()->window()->m_pinned && Desktop::focusState()->window()->m_monitor == m_self)) { if (const auto PLAST = m_activeWorkspace->getLastFocusedWindow(); PLAST) - Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_KEYBIND); + Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_TOGGLE_SPECIAL_WORKSPACE); else g_pInputManager->refocus(); } @@ -1508,7 +1508,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (PMONITOR && PMONITOR->m_activeSpecialWorkspace == pWorkspace) { PMONITOR->m_activeSpecialWorkspace.reset(); - g_layoutManager->recalculateMonitor(PMONITOR); + g_layoutManager->recalculateMonitor(PMONITOR, Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE); g_pHyprRenderer->damageMonitor(PMONITOR); g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + PMONITOR->m_name}); g_pEventManager->postEvent(SHyprIPCEvent{"activespecialv2", ",," + PMONITOR->m_name}); @@ -1573,11 +1573,11 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { } } - g_layoutManager->recalculateMonitor(m_self.lock()); + g_layoutManager->recalculateMonitor(m_self.lock(), Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE); if (!(Desktop::focusState()->window() && Desktop::focusState()->window()->m_pinned && Desktop::focusState()->window()->m_monitor == m_self)) { if (const auto PLAST = pWorkspace->getLastFocusedWindow(); PLAST) - Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_KEYBIND); + Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_TOGGLE_SPECIAL_WORKSPACE); else g_pInputManager->refocus(); } diff --git a/src/layout/LayoutManager.cpp b/src/layout/LayoutManager.cpp index f90cedf63..f9a2821e9 100644 --- a/src/layout/LayoutManager.cpp +++ b/src/layout/LayoutManager.cpp @@ -332,11 +332,22 @@ void CLayoutManager::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SPm_activeSpecialWorkspace) - m->m_activeSpecialWorkspace->m_space->recalculate(); - if (m->m_activeWorkspace) - m->m_activeWorkspace->m_space->recalculate(); +void CLayoutManager::recalculateMonitor(PHLMONITOR m, std::optional reason) { + if (m->m_activeSpecialWorkspace) { + if (reason == RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE) + m->m_activeSpecialWorkspace->m_space->recalculate(RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE); + else + m->m_activeSpecialWorkspace->m_space->recalculate(); + return; + } + + if (m->m_activeWorkspace) { + if (reason == RECALCULATE_MONITOR_REASON_WORKSPACE_CHANGE) + m->m_activeWorkspace->m_space->recalculate(RECALCULATE_REASON_WORKSPACE_CHANGE); + else + m->m_activeWorkspace->m_space->recalculate(); + return; + } } void CLayoutManager::invalidateMonitorGeometries(PHLMONITOR m) { diff --git a/src/layout/LayoutManager.hpp b/src/layout/LayoutManager.hpp index 2660cf289..19f18f47b 100644 --- a/src/layout/LayoutManager.hpp +++ b/src/layout/LayoutManager.hpp @@ -45,6 +45,11 @@ namespace Layout { CLayoutManager(); ~CLayoutManager() = default; + enum eRecalculateMonitorReason : uint8_t { + RECALCULATE_MONITOR_REASON_WORKSPACE_CHANGE, + RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE + }; + void newTarget(SP target, SP space); void removeTarget(SP target); @@ -75,8 +80,8 @@ namespace Layout { void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP target, eMouseBindMode mode, int corner, const Vector2D& beginSize); - void invalidateMonitorGeometries(PHLMONITOR); - void recalculateMonitor(PHLMONITOR); + void invalidateMonitorGeometries(PHLMONITOR); + void recalculateMonitor(PHLMONITOR, std::optional reason = std::nullopt); const UP& dragController(); diff --git a/src/layout/algorithm/Algorithm.cpp b/src/layout/algorithm/Algorithm.cpp index b22eb9bfc..3867d352f 100644 --- a/src/layout/algorithm/Algorithm.cpp +++ b/src/layout/algorithm/Algorithm.cpp @@ -101,9 +101,9 @@ size_t CAlgorithm::floatingTargets() const { return m_floatingTargets.size(); } -void CAlgorithm::recalculate() { - m_tiled->recalculate(); - m_floating->recalculate(); +void CAlgorithm::recalculate(std::optional reason) { + m_tiled->recalculate(reason); + m_floating->recalculate(reason); const auto PWORKSPACE = m_space->workspace(); if (!PWORKSPACE) diff --git a/src/layout/algorithm/Algorithm.hpp b/src/layout/algorithm/Algorithm.hpp index 8b9e471d2..24701d0ec 100644 --- a/src/layout/algorithm/Algorithm.hpp +++ b/src/layout/algorithm/Algorithm.hpp @@ -5,6 +5,7 @@ #include "../../helpers/memory/Memory.hpp" #include "../LayoutManager.hpp" +#include "layout/space/Space.hpp" #include #include @@ -34,8 +35,8 @@ namespace Layout { Config::ErrorResult layoutMsg(const std::string_view& sv); std::optional predictSizeForNewTiledTarget(); - void recalculate(); - void recenter(SP t); + void recalculate(std::optional reason = std::nullopt); + void recenter(SP t); void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); void moveTarget(const Vector2D& Δ, SP target); diff --git a/src/layout/algorithm/FloatingAlgorithm.cpp b/src/layout/algorithm/FloatingAlgorithm.cpp index 058887bf0..f3c286277 100644 --- a/src/layout/algorithm/FloatingAlgorithm.cpp +++ b/src/layout/algorithm/FloatingAlgorithm.cpp @@ -4,7 +4,7 @@ using namespace Layout; -void IFloatingAlgorithm::recalculate() { +void IFloatingAlgorithm::recalculate(std::optional reason) { ; } diff --git a/src/layout/algorithm/FloatingAlgorithm.hpp b/src/layout/algorithm/FloatingAlgorithm.hpp index 40e530343..936f00b59 100644 --- a/src/layout/algorithm/FloatingAlgorithm.hpp +++ b/src/layout/algorithm/FloatingAlgorithm.hpp @@ -22,7 +22,7 @@ namespace Layout { virtual void recenter(SP t); - virtual void recalculate(); + virtual void recalculate(std::optional reason = std::nullopt); protected: IFloatingAlgorithm() = default; diff --git a/src/layout/algorithm/ModeAlgorithm.hpp b/src/layout/algorithm/ModeAlgorithm.hpp index e53d4391e..08de09eb4 100644 --- a/src/layout/algorithm/ModeAlgorithm.hpp +++ b/src/layout/algorithm/ModeAlgorithm.hpp @@ -5,6 +5,7 @@ #include "../../helpers/memory/Memory.hpp" #include "../LayoutManager.hpp" +#include "layout/space/Space.hpp" #include @@ -30,7 +31,7 @@ namespace Layout { virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE) = 0; // recalculate layout - virtual void recalculate() = 0; + virtual void recalculate(std::optional reason = std::nullopt) = 0; // swap targets virtual void swapTargets(SP a, SP b) = 0; diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp index 100856be3..c8509da5d 100644 --- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp +++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp @@ -488,7 +488,7 @@ void CDwindleAlgorithm::swapTargets(SP a, SP b) { nodeB->pTarget = a; } -void CDwindleAlgorithm::recalculate() { +void CDwindleAlgorithm::recalculate(std::optional reason) { calculateWorkspace(); } diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp index 300daa639..85eea2fcf 100644 --- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp +++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp @@ -35,7 +35,7 @@ namespace Layout::Tiled { virtual void removeTarget(SP target); virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void recalculate(std::optional reason = std::nullopt); virtual SP getNextCandidate(SP old); diff --git a/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp b/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp index a0ea13c34..abaf05d75 100644 --- a/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp +++ b/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp @@ -424,7 +424,7 @@ void CMasterAlgorithm::moveTargetInDirection(SP t, Math::eDirection dir } } -void CMasterAlgorithm::recalculate() { +void CMasterAlgorithm::recalculate(std::optional reason) { calculateWorkspace(); } diff --git a/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp b/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp index 00e827841..cd8fa278a 100644 --- a/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp +++ b/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp @@ -53,7 +53,7 @@ namespace Layout::Tiled { virtual void removeTarget(SP target); virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void recalculate(std::optional reason = std::nullopt); virtual SP getNextCandidate(SP old); diff --git a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp index 84b4f9e2c..c3e80053a 100644 --- a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp +++ b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp @@ -125,7 +125,7 @@ void CMonocleAlgorithm::resizeTarget(const Vector2D& Δ, SP target, eRe // monocle layout doesn't support manual resizing, all windows are fullscreen } -void CMonocleAlgorithm::recalculate() { +void CMonocleAlgorithm::recalculate(std::optional reason) { if (m_targetDatas.empty()) return; diff --git a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp index 3f07748b0..60e52bd3e 100644 --- a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp +++ b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp @@ -25,8 +25,8 @@ namespace Layout::Tiled { virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); virtual void removeTarget(SP target); - virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + virtual void recalculate(std::optional reason = std::nullopt); virtual SP getNextCandidate(SP old); diff --git a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp index 28941109d..7bca0f9e1 100644 --- a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp +++ b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp @@ -796,7 +796,7 @@ void CScrollingAlgorithm::resizeTarget(const Vector2D& delta, SP target m_scrollingData->recalculate(true); } -void CScrollingAlgorithm::recalculate() { +void CScrollingAlgorithm::recalculate(std::optional 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) @@ -807,8 +807,11 @@ 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 scrolling tape move when switching workspaces when target is scrolling (special or not) + if (reason != RECALCULATE_REASON_WORKSPACE_CHANGE && reason != RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE) + focusOnInput(Desktop::focusState()->window()->layoutTarget(), INPUT_MODE_KB); + } } m_scrollingData->recalculate(); diff --git a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp index 288d15a62..7c430a2a6 100644 --- a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp +++ b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp @@ -98,8 +98,8 @@ namespace Layout::Tiled { virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); virtual void removeTarget(SP target); - virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + virtual void recalculate(std::optional reason = std::nullopt); virtual SP getNextCandidate(SP old); diff --git a/src/layout/space/Space.cpp b/src/layout/space/Space.cpp index 26c02aaec..7d95e1b3f 100644 --- a/src/layout/space/Space.cpp +++ b/src/layout/space/Space.cpp @@ -146,11 +146,11 @@ SP CSpace::algorithm() const { return m_algorithm; } -void CSpace::recalculate() { +void CSpace::recalculate(std::optional reason) { recheckWorkArea(); if (m_algorithm) - m_algorithm->recalculate(); + m_algorithm->recalculate(reason); } void CSpace::setFullscreen(SP t, eFullscreenMode mode) { diff --git a/src/layout/space/Space.hpp b/src/layout/space/Space.hpp index 5d7f9d014..c116c6d6e 100644 --- a/src/layout/space/Space.hpp +++ b/src/layout/space/Space.hpp @@ -12,6 +12,13 @@ #include namespace Layout { + + enum eRecalculateReason : uint8_t { + RECALCULATE_REASON_WORKSPACE_CHANGE, + RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE, + }; + + class ITarget; class CAlgorithm; @@ -34,7 +41,7 @@ namespace Layout { void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); - void recalculate(); + void recalculate(std::optional reason = std::nullopt); void toggleTargetFloating(SP t);