diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2025-12-20 22:16:13 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-20 22:16:13 +0000 |
| commit | b9bef6955487b75d13cfedd230bdc4adafedd115 (patch) | |
| tree | 21400bb6bbb37651ad8e2f3338d2fa5e317b4098 /src/desktop/history/WorkspaceHistoryTracker.cpp | |
| parent | 70f54a1e1ba3478a56faf82431b2770bd727431d (diff) | |
Desktop/history: Move history to desktop (#12676)
Diffstat (limited to 'src/desktop/history/WorkspaceHistoryTracker.cpp')
| -rw-r--r-- | src/desktop/history/WorkspaceHistoryTracker.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
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<CWorkspaceHistoryTracker> History::workspaceTracker() { + static SP<CWorkspaceHistoryTracker> tracker = makeShared<CWorkspaceHistoryTracker>(); + return tracker; +} + +CWorkspaceHistoryTracker::CWorkspaceHistoryTracker() { + static auto P = g_pHookSystem->hookDynamic("workspace", [this](void* self, SCallbackInfo& info, std::any data) { + auto workspace = std::any_cast<PHLWORKSPACE>(data); + track(workspace); + }); + + static auto P1 = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { + auto mon = std::any_cast<PHLMONITOR>(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<Hyprlang::INT>("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}; +} |
