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
This commit is contained in:
erstarr 2026-04-04 04:09:20 +02:00
parent 7c1592297c
commit 8ccf0f53d4
19 changed files with 67 additions and 37 deletions

View file

@ -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,

View file

@ -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();
}

View file

@ -332,11 +332,22 @@ void CLayoutManager::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP<I
sourceSize = {sourceX.end - sourceX.start, sourceY.end - sourceY.start};
}
void CLayoutManager::recalculateMonitor(PHLMONITOR m) {
if (m->m_activeSpecialWorkspace)
m->m_activeSpecialWorkspace->m_space->recalculate();
if (m->m_activeWorkspace)
m->m_activeWorkspace->m_space->recalculate();
void CLayoutManager::recalculateMonitor(PHLMONITOR m, std::optional<eRecalculateMonitorReason> 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) {

View file

@ -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<ITarget> target, SP<CSpace> space);
void removeTarget(SP<ITarget> target);
@ -75,8 +80,8 @@ namespace Layout {
void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP<ITarget> target, eMouseBindMode mode, int corner, const Vector2D& beginSize);
void invalidateMonitorGeometries(PHLMONITOR);
void recalculateMonitor(PHLMONITOR);
void invalidateMonitorGeometries(PHLMONITOR);
void recalculateMonitor(PHLMONITOR, std::optional<eRecalculateMonitorReason> reason = std::nullopt);
const UP<Supplementary::CDragStateController>& dragController();

View file

@ -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<eRecalculateReason> reason) {
m_tiled->recalculate(reason);
m_floating->recalculate(reason);
const auto PWORKSPACE = m_space->workspace();
if (!PWORKSPACE)

View file

@ -5,6 +5,7 @@
#include "../../helpers/memory/Memory.hpp"
#include "../LayoutManager.hpp"
#include "layout/space/Space.hpp"
#include <expected>
#include <optional>
@ -34,8 +35,8 @@ namespace Layout {
Config::ErrorResult layoutMsg(const std::string_view& sv);
std::optional<Vector2D> predictSizeForNewTiledTarget();
void recalculate();
void recenter(SP<ITarget> t);
void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
void recenter(SP<ITarget> t);
void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
void moveTarget(const Vector2D& Δ, SP<ITarget> target);

View file

@ -4,7 +4,7 @@
using namespace Layout;
void IFloatingAlgorithm::recalculate() {
void IFloatingAlgorithm::recalculate(std::optional<eRecalculateReason> reason) {
;
}

View file

@ -22,7 +22,7 @@ namespace Layout {
virtual void recenter(SP<ITarget> t);
virtual void recalculate();
virtual void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
protected:
IFloatingAlgorithm() = default;

View file

@ -5,6 +5,7 @@
#include "../../helpers/memory/Memory.hpp"
#include "../LayoutManager.hpp"
#include "layout/space/Space.hpp"
#include <expected>
@ -30,7 +31,7 @@ namespace Layout {
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE) = 0;
// recalculate layout
virtual void recalculate() = 0;
virtual void recalculate(std::optional<eRecalculateReason> reason = std::nullopt) = 0;
// swap targets
virtual void swapTargets(SP<ITarget> a, SP<ITarget> b) = 0;

View file

@ -488,7 +488,7 @@ void CDwindleAlgorithm::swapTargets(SP<ITarget> a, SP<ITarget> b) {
nodeB->pTarget = a;
}
void CDwindleAlgorithm::recalculate() {
void CDwindleAlgorithm::recalculate(std::optional<eRecalculateReason> reason) {
calculateWorkspace();
}

View file

@ -35,7 +35,7 @@ namespace Layout::Tiled {
virtual void removeTarget(SP<ITarget> target);
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
virtual void recalculate();
virtual void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
virtual SP<ITarget> getNextCandidate(SP<ITarget> old);

View file

@ -424,7 +424,7 @@ void CMasterAlgorithm::moveTargetInDirection(SP<ITarget> t, Math::eDirection dir
}
}
void CMasterAlgorithm::recalculate() {
void CMasterAlgorithm::recalculate(std::optional<eRecalculateReason> reason) {
calculateWorkspace();
}

View file

@ -53,7 +53,7 @@ namespace Layout::Tiled {
virtual void removeTarget(SP<ITarget> target);
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
virtual void recalculate();
virtual void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
virtual SP<ITarget> getNextCandidate(SP<ITarget> old);

View file

@ -125,7 +125,7 @@ void CMonocleAlgorithm::resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRe
// monocle layout doesn't support manual resizing, all windows are fullscreen
}
void CMonocleAlgorithm::recalculate() {
void CMonocleAlgorithm::recalculate(std::optional<eRecalculateReason> reason) {
if (m_targetDatas.empty())
return;

View file

@ -25,8 +25,8 @@ namespace Layout::Tiled {
virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
virtual void removeTarget(SP<ITarget> target);
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
virtual void recalculate();
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
virtual void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
virtual SP<ITarget> getNextCandidate(SP<ITarget> old);

View file

@ -796,7 +796,7 @@ void CScrollingAlgorithm::resizeTarget(const Vector2D& delta, SP<ITarget> target
m_scrollingData->recalculate(true);
}
void CScrollingAlgorithm::recalculate() {
void CScrollingAlgorithm::recalculate(std::optional<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)
@ -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();

View file

@ -98,8 +98,8 @@ namespace Layout::Tiled {
virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
virtual void removeTarget(SP<ITarget> target);
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
virtual void recalculate();
virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
virtual void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
virtual SP<ITarget> getNextCandidate(SP<ITarget> old);

View file

@ -146,11 +146,11 @@ SP<CAlgorithm> CSpace::algorithm() const {
return m_algorithm;
}
void CSpace::recalculate() {
void CSpace::recalculate(std::optional<eRecalculateReason> reason) {
recheckWorkArea();
if (m_algorithm)
m_algorithm->recalculate();
m_algorithm->recalculate(reason);
}
void CSpace::setFullscreen(SP<ITarget> t, eFullscreenMode mode) {

View file

@ -12,6 +12,13 @@
#include <expected>
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<ITarget> t, Math::eDirection dir, bool silent);
void recalculate();
void recalculate(std::optional<eRecalculateReason> reason = std::nullopt);
void toggleTargetFloating(SP<ITarget> t);