From b9bef6955487b75d13cfedd230bdc4adafedd115 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 20 Dec 2025 22:16:13 +0000 Subject: [PATCH] Desktop/history: Move history to desktop (#12676) --- src/Compositor.cpp | 23 +-- src/debug/HyprCtl.cpp | 8 +- src/desktop/Workspace.cpp | 22 --- src/desktop/Workspace.hpp | 49 +++--- src/desktop/history/WindowHistoryTracker.cpp | 55 ++++++ src/desktop/history/WindowHistoryTracker.hpp | 30 ++++ .../history/WorkspaceHistoryTracker.cpp | 158 ++++++++++++++++++ .../history/WorkspaceHistoryTracker.hpp | 54 ++++++ src/desktop/state/FocusState.cpp | 47 +----- src/desktop/state/FocusState.hpp | 29 ++-- src/desktop/view/Window.cpp | 3 +- src/helpers/MiscFunctions.cpp | 3 +- src/helpers/Monitor.cpp | 23 --- src/helpers/Monitor.hpp | 4 - src/managers/KeybindManager.cpp | 40 ++--- src/managers/KeybindManager.hpp | 2 +- .../input/UnifiedWorkspaceSwipeGesture.cpp | 3 - 17 files changed, 372 insertions(+), 181 deletions(-) create mode 100644 src/desktop/history/WindowHistoryTracker.cpp create mode 100644 src/desktop/history/WindowHistoryTracker.hpp create mode 100644 src/desktop/history/WorkspaceHistoryTracker.cpp create mode 100644 src/desktop/history/WorkspaceHistoryTracker.hpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7b5e0324..9c806fdd 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -5,6 +5,8 @@ #include "debug/log/Logger.hpp" #include "desktop/DesktopTypes.hpp" #include "desktop/state/FocusState.hpp" +#include "desktop/history/WindowHistoryTracker.hpp" +#include "desktop/history/WorkspaceHistoryTracker.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" #include "config/ConfigWatcher.hpp" @@ -661,6 +663,11 @@ void CCompositor::initManagers(eManagersInitStage stage) { Log::logger->log(Log::DEBUG, "Creating the SeatManager!"); g_pSeatManager = makeUnique(); + + // init focus state els + Desktop::History::windowTracker(); + Desktop::History::workspaceTracker(); + } break; case STAGE_LATE: { Log::logger->log(Log::DEBUG, "Creating CHyprCtl"); @@ -1447,16 +1454,14 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks // get idx int windowIDX = -1; - const auto& HISTORY = Desktop::focusState()->windowHistory(); - for (size_t i = 0; i < HISTORY.size(); ++i) { + const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); + for (int64_t i = HISTORY.size() - 1; i >= 0; --i) { if (HISTORY[i] == w) { windowIDX = i; break; } } - windowIDX = Desktop::focusState()->windowHistory().size() - windowIDX; - if (windowIDX > leaderValue) { leaderValue = windowIDX; leaderWindow = w; @@ -1560,10 +1565,9 @@ static PHLWINDOW getWeakWindowPred(Iterator cur, Iterator end, Iterator begin, c PHLWINDOW CCompositor::getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly, std::optional floating, bool visible, bool next) { const auto FINDER = [&](const PHLWINDOWREF& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); }; // also m_vWindowFocusHistory has reverse order, so when it is next - we need to reverse again - return next ? getWeakWindowPred(std::ranges::find(Desktop::focusState()->windowHistory() | std::views::reverse, cur), Desktop::focusState()->windowHistory().rend(), - Desktop::focusState()->windowHistory().rbegin(), FINDER) : - getWeakWindowPred(std::ranges::find(Desktop::focusState()->windowHistory(), cur), Desktop::focusState()->windowHistory().end(), - Desktop::focusState()->windowHistory().begin(), FINDER); + const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); + return next ? getWeakWindowPred(std::ranges::find(HISTORY, cur), HISTORY.end(), HISTORY.begin(), FINDER) : + getWeakWindowPred(std::ranges::find(HISTORY | std::views::reverse, cur), HISTORY.rend(), HISTORY.rbegin(), FINDER); } PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::optional floating, bool visible, bool prev) { @@ -1808,9 +1812,6 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor pMonitorA->m_activeWorkspace = PWORKSPACEB; pMonitorB->m_activeWorkspace = PWORKSPACEA; - PWORKSPACEA->rememberPrevWorkspace(PWORKSPACEB); - PWORKSPACEB->rememberPrevWorkspace(PWORKSPACEA); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorA->m_id); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorB->m_id); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 90adab91..41b34e8a 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -45,6 +45,7 @@ using namespace Hyprutils::OS; #include "helpers/MiscFunctions.hpp" #include "../desktop/view/LayerSurface.hpp" #include "../desktop/rule/Engine.hpp" +#include "../desktop/history/WindowHistoryTracker.hpp" #include "../desktop/state/FocusState.hpp" #include "../version.h" @@ -354,9 +355,10 @@ static std::string getGroupedData(PHLWINDOW w, eHyprCtlOutputFormat format) { std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { auto getFocusHistoryID = [](PHLWINDOW wnd) -> int { - for (size_t i = 0; i < Desktop::focusState()->windowHistory().size(); ++i) { - if (Desktop::focusState()->windowHistory()[i].lock() == wnd) - return i; + const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); + for (size_t i = 0; i < HISTORY.size(); ++i) { + if (HISTORY[i].lock() == wnd) + return HISTORY.size() - i - 1; // reverse order for backwards compat } return -1; }; diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index cbb584b6..2895137d 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -55,10 +55,6 @@ void CWorkspace::init(PHLWORKSPACE self) { EMIT_HOOK_EVENT("createWorkspace", this); } -SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName() const { - return m_prevWorkspace; -} - CWorkspace::~CWorkspace() { Log::logger->log(Log::DEBUG, "Destroying workspace ID {}", m_id); @@ -82,24 +78,6 @@ PHLWINDOW CWorkspace::getLastFocusedWindow() { return m_lastFocusedWindow.lock(); } -void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { - if (!prev) { - m_prevWorkspace.id = -1; - m_prevWorkspace.name = ""; - return; - } - - if (prev->m_id == m_id) { - Log::logger->log(Log::DEBUG, "Tried to set prev workspace to the same as current one"); - return; - } - - m_prevWorkspace.id = prev->m_id; - m_prevWorkspace.name = prev->m_name; - - prev->m_monitor->addPrevWorkspaceID(prev->m_id); -} - std::string CWorkspace::getConfigName() { if (m_isSpecialWorkspace) { return m_name; diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 392ef642..1aad1aaa 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -57,29 +57,27 @@ class CWorkspace { bool m_wasCreatedEmpty = true; // Inert: destroyed and invalid. If this is true, release the ptr you have. - bool inert(); - MONITORID monitorID(); - PHLWINDOW getLastFocusedWindow(); - void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); - std::string getConfigName(); - bool matchesStaticSelector(const std::string& selector); - void markInert(); - SWorkspaceIDName getPrevWorkspaceIDName() const; - void updateWindowDecos(); - void updateWindowData(); - int getWindows(std::optional onlyTiled = {}, std::optional onlyPinned = {}, std::optional onlyVisible = {}); - int getGroups(std::optional onlyTiled = {}, std::optional onlyPinned = {}, std::optional onlyVisible = {}); - bool hasUrgentWindow(); - PHLWINDOW getFirstWindow(); - PHLWINDOW getTopLeftWindow(); - PHLWINDOW getFullscreenWindow(); - bool isVisible(); - bool isVisibleNotCovered(); - void rename(const std::string& name = ""); - void forceReportSizesToWindows(); - void updateWindows(); - void setPersistent(bool persistent); - bool isPersistent(); + bool inert(); + MONITORID monitorID(); + PHLWINDOW getLastFocusedWindow(); + std::string getConfigName(); + bool matchesStaticSelector(const std::string& selector); + void markInert(); + void updateWindowDecos(); + void updateWindowData(); + int getWindows(std::optional onlyTiled = {}, std::optional onlyPinned = {}, std::optional onlyVisible = {}); + int getGroups(std::optional onlyTiled = {}, std::optional onlyPinned = {}, std::optional onlyVisible = {}); + bool hasUrgentWindow(); + PHLWINDOW getFirstWindow(); + PHLWINDOW getTopLeftWindow(); + PHLWINDOW getFullscreenWindow(); + bool isVisible(); + bool isVisibleNotCovered(); + void rename(const std::string& name = ""); + void forceReportSizesToWindows(); + void updateWindows(); + void setPersistent(bool persistent); + bool isPersistent(); struct { CSignalT<> destroy; @@ -89,10 +87,7 @@ class CWorkspace { } m_events; private: - void init(PHLWORKSPACE self); - // Previous workspace ID and name is stored during a workspace change, allowing travel - // to the previous workspace. - SWorkspaceIDName m_prevWorkspace; + void init(PHLWORKSPACE self); SP m_focusedWindowHook; bool m_inert = true; diff --git a/src/desktop/history/WindowHistoryTracker.cpp b/src/desktop/history/WindowHistoryTracker.cpp new file mode 100644 index 00000000..5dc0742f --- /dev/null +++ b/src/desktop/history/WindowHistoryTracker.cpp @@ -0,0 +1,55 @@ +#include "WindowHistoryTracker.hpp" + +#include "../../managers/HookSystemManager.hpp" +#include "../view/Window.hpp" + +using namespace Desktop; +using namespace Desktop::History; + +SP History::windowTracker() { + static SP tracker = makeShared(); + return tracker; +} + +CWindowHistoryTracker::CWindowHistoryTracker() { + static auto P = g_pHookSystem->hookDynamic("openWindowEarly", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + // add a last track + m_history.insert(m_history.begin(), window); + }); + + static auto P1 = g_pHookSystem->hookDynamic("activeWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + track(window); + }); +} + +void CWindowHistoryTracker::track(PHLWINDOW w) { + std::erase(m_history, w); + m_history.emplace_back(w); +} + +const std::vector& CWindowHistoryTracker::fullHistory() { + gc(); + return m_history; +} + +std::vector CWindowHistoryTracker::historyForWorkspace(PHLWORKSPACE ws) { + gc(); + std::vector windows; + + for (const auto& w : m_history) { + if (w->m_workspace != ws) + continue; + + windows.emplace_back(w); + } + + return windows; +} + +void CWindowHistoryTracker::gc() { + std::erase_if(m_history, [](const auto& e) { return !e; }); +} diff --git a/src/desktop/history/WindowHistoryTracker.hpp b/src/desktop/history/WindowHistoryTracker.hpp new file mode 100644 index 00000000..92645683 --- /dev/null +++ b/src/desktop/history/WindowHistoryTracker.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "../DesktopTypes.hpp" + +#include + +namespace Desktop::History { + class CWindowHistoryTracker { + public: + CWindowHistoryTracker(); + ~CWindowHistoryTracker() = default; + + CWindowHistoryTracker(const CWindowHistoryTracker&) = delete; + CWindowHistoryTracker(CWindowHistoryTracker&) = delete; + CWindowHistoryTracker(CWindowHistoryTracker&&) = delete; + + // History is ordered old -> new, meaning .front() is oldest, while .back() is newest + + const std::vector& fullHistory(); + std::vector historyForWorkspace(PHLWORKSPACE ws); + + private: + std::vector m_history; + + void track(PHLWINDOW w); + void gc(); + }; + + SP windowTracker(); +}; \ No newline at end of file diff --git a/src/desktop/history/WorkspaceHistoryTracker.cpp b/src/desktop/history/WorkspaceHistoryTracker.cpp new file mode 100644 index 00000000..bfedda13 --- /dev/null +++ b/src/desktop/history/WorkspaceHistoryTracker.cpp @@ -0,0 +1,158 @@ +#include "WorkspaceHistoryTracker.hpp" + +#include "../../helpers/Monitor.hpp" +#include "../Workspace.hpp" +#include "../../managers/HookSystemManager.hpp" +#include "../../config/ConfigValue.hpp" + +using namespace Desktop; +using namespace Desktop::History; + +SP History::workspaceTracker() { + static SP tracker = makeShared(); + return tracker; +} + +CWorkspaceHistoryTracker::CWorkspaceHistoryTracker() { + static auto P = g_pHookSystem->hookDynamic("workspace", [this](void* self, SCallbackInfo& info, std::any data) { + auto workspace = std::any_cast(data); + track(workspace); + }); + + static auto P1 = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { + auto mon = std::any_cast(data); + track(mon); + }); +} + +CWorkspaceHistoryTracker::SMonitorData& CWorkspaceHistoryTracker::dataFor(PHLMONITOR mon) { + for (auto& ref : m_monitorDatas) { + if (ref.monitor != mon) + continue; + + return ref; + } + + return m_monitorDatas.emplace_back(SMonitorData{ + .monitor = mon, + }); +} + +CWorkspaceHistoryTracker::SWorkspacePreviousData& CWorkspaceHistoryTracker::dataFor(PHLWORKSPACE ws) { + for (auto& ref : m_datas) { + if (ref.workspace != ws) + continue; + + return ref; + } + + return m_datas.emplace_back(SWorkspacePreviousData{ + .workspace = ws, + }); +} + +void CWorkspaceHistoryTracker::track(PHLWORKSPACE w) { + if (!w->m_monitor) + return; + + static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); + + auto& data = dataFor(w); + auto& monData = dataFor(w->m_monitor.lock()); + + if (!monData.workspace) { + data.previous.reset(); + data.previousID = WORKSPACE_INVALID; + data.previousName = ""; + return; + } + + if (monData.workspace == w && !*PALLOWWORKSPACECYCLES) { + track(w->m_monitor.lock()); + return; + } + + data.previous = monData.workspace; + data.previousName = monData.workspace->m_name; + data.previousID = monData.workspace->m_id; + data.previousMon = monData.workspace->m_monitor; + + track(w->m_monitor.lock()); +} + +void CWorkspaceHistoryTracker::track(PHLMONITOR mon) { + auto& data = dataFor(mon); + data.workspace = mon->m_activeWorkspace; + data.workspaceName = mon->m_activeWorkspace ? mon->m_activeWorkspace->m_name : ""; + data.workspaceID = mon->activeWorkspaceID(); +} + +void CWorkspaceHistoryTracker::gc() { + std::erase_if(m_datas, [](const auto& e) { return !e.workspace; }); + std::erase_if(m_monitorDatas, [](const auto& e) { return !e.monitor; }); +} + +const CWorkspaceHistoryTracker::SWorkspacePreviousData* CWorkspaceHistoryTracker::previousWorkspace(PHLWORKSPACE ws) { + gc(); + + for (const auto& d : m_datas) { + if (d.workspace != ws) + continue; + return &d; + } + + return &dataFor(ws); +} + +SWorkspaceIDName CWorkspaceHistoryTracker::previousWorkspaceIDName(PHLWORKSPACE ws) { + gc(); + + for (const auto& d : m_datas) { + if (d.workspace != ws) + continue; + return SWorkspaceIDName{.id = d.previousID, .name = d.previousName, .isAutoIDd = d.previousID <= 0}; + } + + auto& d = dataFor(ws); + return SWorkspaceIDName{.id = d.previousID, .name = d.previousName, .isAutoIDd = d.previousID <= 0}; +} + +const CWorkspaceHistoryTracker::SWorkspacePreviousData* CWorkspaceHistoryTracker::previousWorkspace(PHLWORKSPACE ws, PHLMONITOR restrict) { + if (!restrict) + return previousWorkspace(ws); + + auto& data = dataFor(ws); + while (true) { + + // case 1: previous exists + if (data.previous) { + if (data.previous->m_monitor != restrict) { + data = dataFor(data.previous.lock()); + continue; + } + + break; + } + + // case 2: previous doesnt exist, but we have mon + if (data.previousMon) { + if (data.previousMon != restrict) + return nullptr; + + break; + } + + // case 3: no mon and no previous + return nullptr; + } + + return &data; +} + +SWorkspaceIDName CWorkspaceHistoryTracker::previousWorkspaceIDName(PHLWORKSPACE ws, PHLMONITOR restrict) { + const auto DATA = previousWorkspace(ws, restrict); + if (!DATA) + return SWorkspaceIDName{.id = WORKSPACE_INVALID}; + + return SWorkspaceIDName{.id = DATA->previousID, .name = DATA->previousName, .isAutoIDd = DATA->previousID <= 0}; +} diff --git a/src/desktop/history/WorkspaceHistoryTracker.hpp b/src/desktop/history/WorkspaceHistoryTracker.hpp new file mode 100644 index 00000000..4a3c109a --- /dev/null +++ b/src/desktop/history/WorkspaceHistoryTracker.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "../DesktopTypes.hpp" +#include "../../SharedDefs.hpp" +#include "../../macros.hpp" +#include "../../helpers/MiscFunctions.hpp" + +#include + +namespace Desktop::History { + class CWorkspaceHistoryTracker { + public: + CWorkspaceHistoryTracker(); + ~CWorkspaceHistoryTracker() = default; + + CWorkspaceHistoryTracker(const CWorkspaceHistoryTracker&) = delete; + CWorkspaceHistoryTracker(CWorkspaceHistoryTracker&) = delete; + CWorkspaceHistoryTracker(CWorkspaceHistoryTracker&&) = delete; + + struct SWorkspacePreviousData { + PHLWORKSPACEREF workspace; + PHLWORKSPACEREF previous; + PHLMONITORREF previousMon; + std::string previousName = ""; + WORKSPACEID previousID = WORKSPACE_INVALID; + }; + + const SWorkspacePreviousData* previousWorkspace(PHLWORKSPACE ws); + SWorkspaceIDName previousWorkspaceIDName(PHLWORKSPACE ws); + + const SWorkspacePreviousData* previousWorkspace(PHLWORKSPACE ws, PHLMONITOR restrict); + SWorkspaceIDName previousWorkspaceIDName(PHLWORKSPACE ws, PHLMONITOR restrict); + + private: + struct SMonitorData { + PHLMONITORREF monitor; + PHLWORKSPACEREF workspace; + std::string workspaceName = ""; + WORKSPACEID workspaceID = WORKSPACE_INVALID; + }; + + std::vector m_datas; + std::vector m_monitorDatas; + + void track(PHLWORKSPACE w); + void track(PHLMONITOR mon); + void gc(); + + SMonitorData& dataFor(PHLMONITOR mon); + SWorkspacePreviousData& dataFor(PHLWORKSPACE ws); + }; + + SP workspaceTracker(); +}; \ No newline at end of file diff --git a/src/desktop/state/FocusState.cpp b/src/desktop/state/FocusState.cpp index ea869398..e6257690 100644 --- a/src/desktop/state/FocusState.cpp +++ b/src/desktop/state/FocusState.cpp @@ -16,19 +16,7 @@ SP Desktop::focusState() { return state; } -Desktop::CFocusState::CFocusState() { - m_windowOpen = g_pHookSystem->hookDynamic("openWindowEarly", [this](void* self, SCallbackInfo& info, std::any data) { - auto window = std::any_cast(data); - - addWindowToHistory(window); - }); - - m_windowClose = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { - auto window = std::any_cast(data); - - removeWindowFromHistory(window); - }); -} +Desktop::CFocusState::CFocusState() = default; struct SFullscreenWorkspaceFocusResult { PHLWINDOW overrideFocusWindow = nullptr; @@ -73,7 +61,7 @@ static SFullscreenWorkspaceFocusResult onFullscreenWorkspaceFocusWindow(PHLWINDO return {}; } -void CFocusState::fullWindowFocus(PHLWINDOW pWindow, SP surface, bool preserveFocusHistory, bool forceFSCycle) { +void CFocusState::fullWindowFocus(PHLWINDOW pWindow, SP surface, bool forceFSCycle) { if (pWindow) { if (!pWindow->m_workspace) return; @@ -93,10 +81,10 @@ void CFocusState::fullWindowFocus(PHLWINDOW pWindow, SP surf return; } - rawWindowFocus(pWindow, surface, preserveFocusHistory); + rawWindowFocus(pWindow, surface); } -void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP surface, bool preserveFocusHistory) { +void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP surface) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); @@ -164,8 +152,6 @@ void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP surfa const auto PWORKSPACE = pWindow->m_workspace; // This is to fix incorrect feedback on the focus history. PWORKSPACE->m_lastFocusedWindow = pWindow; - if (m_focusMonitor->m_activeWorkspace) - PWORKSPACE->rememberPrevWorkspace(m_focusMonitor->m_activeWorkspace); if (PWORKSPACE->m_isSpecialWorkspace) m_focusMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor else if (PMONITOR) @@ -214,11 +200,6 @@ void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP surfa g_pInputManager->recheckIdleInhibitorStatus(); - if (!preserveFocusHistory) { - // move to front of the window history - moveWindowToLatestInHistory(pWindow); - } - if (*PFOLLOWMOUSE == 0) g_pInputManager->sendMotionEventsToFocused(); @@ -308,23 +289,3 @@ PHLWINDOW CFocusState::window() { PHLMONITOR CFocusState::monitor() { return m_focusMonitor.lock(); } - -const std::vector& CFocusState::windowHistory() { - return m_windowFocusHistory; -} - -void CFocusState::removeWindowFromHistory(PHLWINDOW w) { - std::erase_if(m_windowFocusHistory, [&w](const auto& e) { return !e || e == w; }); -} - -void CFocusState::addWindowToHistory(PHLWINDOW w) { - m_windowFocusHistory.emplace_back(w); -} - -void CFocusState::moveWindowToLatestInHistory(PHLWINDOW w) { - const auto HISTORYPIVOT = std::ranges::find_if(m_windowFocusHistory, [&w](const auto& other) { return other.lock() == w; }); - if (HISTORYPIVOT == m_windowFocusHistory.end()) - Log::logger->log(Log::TRACE, "CFocusState: {} has no pivot in history, ignoring request to move to latest", w); - else - std::rotate(m_windowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); -} diff --git a/src/desktop/state/FocusState.hpp b/src/desktop/state/FocusState.hpp index 2bf0953d..5603b0cc 100644 --- a/src/desktop/state/FocusState.hpp +++ b/src/desktop/state/FocusState.hpp @@ -15,28 +15,21 @@ namespace Desktop { CFocusState(CFocusState&) = delete; CFocusState(const CFocusState&) = delete; - void fullWindowFocus(PHLWINDOW w, SP surface = nullptr, bool preserveFocusHistory = false, bool forceFSCycle = false); - void rawWindowFocus(PHLWINDOW w, SP surface = nullptr, bool preserveFocusHistory = false); - void rawSurfaceFocus(SP s, PHLWINDOW pWindowOwner = nullptr); - void rawMonitorFocus(PHLMONITOR m); + void fullWindowFocus(PHLWINDOW w, SP surface = nullptr, bool forceFSCycle = false); + void rawWindowFocus(PHLWINDOW w, SP surface = nullptr); + void rawSurfaceFocus(SP s, PHLWINDOW pWindowOwner = nullptr); + void rawMonitorFocus(PHLMONITOR m); - SP surface(); - PHLWINDOW window(); - PHLMONITOR monitor(); - const std::vector& windowHistory(); - - void addWindowToHistory(PHLWINDOW w); + SP surface(); + PHLWINDOW window(); + PHLMONITOR monitor(); private: - void removeWindowFromHistory(PHLWINDOW w); - void moveWindowToLatestInHistory(PHLWINDOW w); + WP m_focusSurface; + PHLWINDOWREF m_focusWindow; + PHLMONITORREF m_focusMonitor; - WP m_focusSurface; - PHLWINDOWREF m_focusWindow; - PHLMONITORREF m_focusMonitor; - std::vector m_windowFocusHistory; // first element is the most recently focused - - SP m_windowOpen, m_windowClose; + SP m_windowOpen, m_windowClose; }; SP focusState(); diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index bdb9affe..c2246db8 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -15,6 +15,7 @@ #include "Window.hpp" #include "LayerSurface.hpp" #include "../state/FocusState.hpp" +#include "../history/WindowHistoryTracker.hpp" #include "../../Compositor.hpp" #include "../../render/decorations/CHyprDropShadowDecoration.hpp" #include "../../render/decorations/CHyprGroupBarDecoration.hpp" @@ -1553,7 +1554,7 @@ PHLWINDOW CWindow::getSwallower() { return candidates[0]; // walk up the focus history and find the last focused - for (auto const& w : Desktop::focusState()->windowHistory()) { + for (auto const& w : Desktop::History::windowTracker()->fullHistory() | std::views::reverse) { if (!w) continue; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 79504b31..34b06c2e 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -4,6 +4,7 @@ #include "../Compositor.hpp" #include "../managers/TokenManager.hpp" #include "../desktop/state/FocusState.hpp" +#include "../desktop/history/WorkspaceHistoryTracker.hpp" #include "Monitor.hpp" #include "../config/ConfigManager.hpp" #include "fs/FsUtils.hpp" @@ -179,7 +180,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { if (!valid(PWORKSPACE)) return {WORKSPACE_INVALID}; - const auto PREVWORKSPACEIDNAME = PWORKSPACE->getPrevWorkspaceIDName(); + const auto PREVWORKSPACEIDNAME = Desktop::History::workspaceTracker()->previousWorkspaceIDName(PWORKSPACE); if (PREVWORKSPACEIDNAME.id == -1) return {WORKSPACE_INVALID}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 37e11908..cbb02118 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1480,29 +1480,6 @@ void CMonitor::moveTo(const Vector2D& pos) { m_position = pos; } -SWorkspaceIDName CMonitor::getPrevWorkspaceIDName(const WORKSPACEID id) { - while (!m_prevWorkSpaces.empty()) { - const int PREVID = m_prevWorkSpaces.top(); - m_prevWorkSpaces.pop(); - if (PREVID == id) // skip same workspace - continue; - - // recheck if previous workspace's was moved to another monitor - const auto ws = g_pCompositor->getWorkspaceByID(PREVID); - if (ws && ws->monitorID() == m_id) - return {.id = PREVID, .name = ws->m_name}; - } - - return {.id = WORKSPACE_INVALID}; -} - -void CMonitor::addPrevWorkspaceID(const WORKSPACEID id) { - if (!m_prevWorkSpaces.empty() && m_prevWorkSpaces.top() == id) - return; - - m_prevWorkSpaces.emplace(id); -} - Vector2D CMonitor::middle() { return m_position + m_size / 2.f; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 95e5ce5c..ea2cf185 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -351,10 +351,6 @@ class CMonitor { return m_position == rhs.m_position && m_size == rhs.m_size && m_name == rhs.m_name; } - // workspace previous per monitor functionality - SWorkspaceIDName getPrevWorkspaceIDName(const WORKSPACEID id); - void addPrevWorkspaceID(const WORKSPACEID id); - private: void setupDefaultWS(const SMonitorRule&); WORKSPACEID findAvailableDefaultWS(); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 101374ad..c4d8734e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1,6 +1,8 @@ #include "../config/ConfigValue.hpp" #include "../devices/IKeyboard.hpp" #include "../desktop/state/FocusState.hpp" +#include "../desktop/history/WindowHistoryTracker.hpp" +#include "../desktop/history/WorkspaceHistoryTracker.hpp" #include "../managers/SeatManager.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" @@ -360,7 +362,6 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { const auto PNEWMAINWORKSPACE = monitor->m_activeWorkspace; g_pInputManager->unconstrainMouse(); - PNEWMAINWORKSPACE->rememberPrevWorkspace(PWORKSPACE); const auto PNEWWORKSPACE = monitor->m_activeSpecialWorkspace ? monitor->m_activeSpecialWorkspace : PNEWMAINWORKSPACE; @@ -384,7 +385,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { return true; } -void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory, bool forceFSCycle) { +void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool forceFSCycle) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PNOWARPS = CConfigValue("cursor:no_warps"); @@ -397,10 +398,10 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveF g_pInputManager->unconstrainMouse(); if (PLASTWINDOW && PLASTWINDOW->m_workspace == PWINDOWTOCHANGETO->m_workspace && PLASTWINDOW->isFullscreen()) - Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory, forceFSCycle); + Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, forceFSCycle); else { updateRelativeCursorCoords(); - Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory, forceFSCycle); + Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, forceFSCycle); PWINDOWTOCHANGETO->warpCursor(); // Move mouse focus to the new window if required by current follow_mouse and warp modes @@ -1187,7 +1188,8 @@ static SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSP } const bool PER_MON = args.contains("_per_monitor"); - const SWorkspaceIDName PPREVWS = PER_MON ? PMONITOR->getPrevWorkspaceIDName(PCURRENTWORKSPACE->m_id) : PCURRENTWORKSPACE->getPrevWorkspaceIDName(); + const SWorkspaceIDName PPREVWS = PER_MON ? Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE, PMONITOR.lock()) : + Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE); // Do nothing if there's no previous workspace, otherwise switch to it. if (PPREVWS.id == -1 || PPREVWS.id == PCURRENTWORKSPACE->m_id) { Log::logger->log(Log::DEBUG, "No previous workspace to change to"); @@ -1205,7 +1207,6 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { // Workspace_back_and_forth being enabled means that an attempt to switch to // the current workspace will instead switch to the previous. static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); - static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); static auto PWORKSPACECENTERON = CConfigValue("binds:workspace_center_on"); static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue("binds:hide_special_on_workspace_change"); @@ -1226,7 +1227,8 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) return {}; - const SWorkspaceIDName PPREVWS = args.contains("_per_monitor") ? PMONITOR->getPrevWorkspaceIDName(PCURRENTWORKSPACE->m_id) : PCURRENTWORKSPACE->getPrevWorkspaceIDName(); + const SWorkspaceIDName PPREVWS = args.contains("_per_monitor") ? Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE, PMONITOR) : + Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE); const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_id; if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PPREVWS.id == -1)) { @@ -1261,14 +1263,6 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { Desktop::focusState()->rawMonitorFocus(PMONITORWORKSPACEOWNER); - if (BISWORKSPACECURRENT) { - if (*PALLOWWORKSPACECYCLES) - pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE); - else if (!EXPLICITPREVIOUS && !*PBACKANDFORTH) - pWorkspaceToChangeTo->rememberPrevWorkspace(nullptr); - } else - pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE); - if (*PHIDESPECIALONWORKSPACECHANGE) PMONITORWORKSPACEOWNER->setSpecialWorkspace(nullptr); PMONITORWORKSPACEOWNER->changeWorkspace(pWorkspaceToChangeTo, false, true); @@ -1419,8 +1413,6 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { else if (POLDWS->m_isSpecialWorkspace) POLDWS->m_monitor.lock()->setSpecialWorkspace(nullptr); - pWorkspace->rememberPrevWorkspace(POLDWS); - pMonitor->changeWorkspace(pWorkspace); Desktop::focusState()->fullWindowFocus(PWINDOW); @@ -1514,7 +1506,7 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { // Found window in direction, switch to it if (PWINDOWTOCHANGETO) { - switchToWindow(PWINDOWTOCHANGETO, false, *PFULLCYCLE && PLASTWINDOW->isFullscreen()); + switchToWindow(PWINDOWTOCHANGETO, *PFULLCYCLE && PLASTWINDOW->isFullscreen()); return {}; } @@ -1571,9 +1563,9 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { } SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) { - const auto PWINDOWURGENT = g_pCompositor->getUrgentWindow(); - const auto PWINDOWPREV = Desktop::focusState()->window() ? (Desktop::focusState()->windowHistory().size() < 2 ? nullptr : Desktop::focusState()->windowHistory()[1].lock()) : - (Desktop::focusState()->windowHistory().empty() ? nullptr : Desktop::focusState()->windowHistory()[0].lock()); + const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); + const auto PWINDOWURGENT = g_pCompositor->getUrgentWindow(); + const auto PWINDOWPREV = Desktop::focusState()->window() ? (HISTORY.size() < 2 ? nullptr : HISTORY[1].lock()) : (HISTORY.empty() ? nullptr : HISTORY[0].lock()); if (!PWINDOWURGENT && !PWINDOWPREV) return {.success = false, .error = "Window not found"}; @@ -1584,8 +1576,8 @@ SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) { } SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) { - const auto PWINDOWPREV = Desktop::focusState()->window() ? (Desktop::focusState()->windowHistory().size() < 2 ? nullptr : Desktop::focusState()->windowHistory()[1].lock()) : - (Desktop::focusState()->windowHistory().empty() ? nullptr : Desktop::focusState()->windowHistory()[0].lock()); + const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); + const auto PWINDOWPREV = Desktop::focusState()->window() ? (HISTORY.size() < 2 ? nullptr : HISTORY[1].lock()) : (HISTORY.empty() ? nullptr : HISTORY[0].lock()); if (!PWINDOWPREV) return {.success = false, .error = "Window not found"}; @@ -2064,7 +2056,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args } static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); - const auto PREVWS = pWorkspace->getPrevWorkspaceIDName(); + const auto PREVWS = Desktop::History::workspaceTracker()->previousWorkspaceIDName(pWorkspace); if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) { // Workspace to focus is previous workspace diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index b5b200db..d4b1bf66 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -164,7 +164,7 @@ class CKeybindManager { static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); - static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory = false, bool forceFSCycle = false); + static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool forceFSCycle = false); static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace, const std::string& execRuleToken = ""); static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); diff --git a/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp b/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp index c952c0c8..c2c8a72a 100644 --- a/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp +++ b/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp @@ -246,7 +246,6 @@ void CUnifiedWorkspaceSwipeGesture::end() { else { m_monitor->changeWorkspace(g_pCompositor->createNewWorkspace(workspaceIDLeft, m_monitor->m_id)); PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); - PWORKSPACEL->rememberPrevWorkspace(m_workspaceBegin); } PWORKSPACEL->m_renderOffset->setValue(RENDEROFFSET); @@ -273,7 +272,6 @@ void CUnifiedWorkspaceSwipeGesture::end() { else { m_monitor->changeWorkspace(g_pCompositor->createNewWorkspace(workspaceIDRight, m_monitor->m_id)); PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); - PWORKSPACER->rememberPrevWorkspace(m_workspaceBegin); } PWORKSPACER->m_renderOffset->setValue(RENDEROFFSET); @@ -292,7 +290,6 @@ void CUnifiedWorkspaceSwipeGesture::end() { pSwitchedTo = PWORKSPACER; } - pSwitchedTo->rememberPrevWorkspace(m_workspaceBegin); g_pHyprRenderer->damageMonitor(m_monitor.lock());