summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-12-20 22:16:13 +0000
committerGitHub <noreply@github.com>2025-12-20 22:16:13 +0000
commitb9bef6955487b75d13cfedd230bdc4adafedd115 (patch)
tree21400bb6bbb37651ad8e2f3338d2fa5e317b4098
parent70f54a1e1ba3478a56faf82431b2770bd727431d (diff)
Desktop/history: Move history to desktop (#12676)
-rw-r--r--src/Compositor.cpp23
-rw-r--r--src/debug/HyprCtl.cpp8
-rw-r--r--src/desktop/Workspace.cpp22
-rw-r--r--src/desktop/Workspace.hpp49
-rw-r--r--src/desktop/history/WindowHistoryTracker.cpp55
-rw-r--r--src/desktop/history/WindowHistoryTracker.hpp30
-rw-r--r--src/desktop/history/WorkspaceHistoryTracker.cpp158
-rw-r--r--src/desktop/history/WorkspaceHistoryTracker.hpp54
-rw-r--r--src/desktop/state/FocusState.cpp47
-rw-r--r--src/desktop/state/FocusState.hpp29
-rw-r--r--src/desktop/view/Window.cpp3
-rw-r--r--src/helpers/MiscFunctions.cpp3
-rw-r--r--src/helpers/Monitor.cpp23
-rw-r--r--src/helpers/Monitor.hpp4
-rw-r--r--src/managers/KeybindManager.cpp40
-rw-r--r--src/managers/KeybindManager.hpp2
-rw-r--r--src/managers/input/UnifiedWorkspaceSwipeGesture.cpp3
17 files changed, 372 insertions, 181 deletions
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<CSeatManager>();
+
+ // 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<bool> 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<bool> 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<bool> onlyTiled = {}, std::optional<bool> onlyPinned = {}, std::optional<bool> onlyVisible = {});
- int getGroups(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyPinned = {}, std::optional<bool> 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<bool> onlyTiled = {}, std::optional<bool> onlyPinned = {}, std::optional<bool> onlyVisible = {});
+ int getGroups(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyPinned = {}, std::optional<bool> 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<HOOK_CALLBACK_FN> 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<CWindowHistoryTracker> History::windowTracker() {
+ static SP<CWindowHistoryTracker> tracker = makeShared<CWindowHistoryTracker>();
+ return tracker;
+}
+
+CWindowHistoryTracker::CWindowHistoryTracker() {
+ static auto P = g_pHookSystem->hookDynamic("openWindowEarly", [this](void* self, SCallbackInfo& info, std::any data) {
+ auto window = std::any_cast<PHLWINDOW>(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<PHLWINDOW>(data);
+
+ track(window);
+ });
+}
+
+void CWindowHistoryTracker::track(PHLWINDOW w) {
+ std::erase(m_history, w);
+ m_history.emplace_back(w);
+}
+
+const std::vector<PHLWINDOWREF>& CWindowHistoryTracker::fullHistory() {
+ gc();
+ return m_history;
+}
+
+std::vector<PHLWINDOWREF> CWindowHistoryTracker::historyForWorkspace(PHLWORKSPACE ws) {
+ gc();
+ std::vector<PHLWINDOWREF> 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 <vector>
+
+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<PHLWINDOWREF>& fullHistory();
+ std::vector<PHLWINDOWREF> historyForWorkspace(PHLWORKSPACE ws);
+
+ private:
+ std::vector<PHLWINDOWREF> m_history;
+
+ void track(PHLWINDOW w);
+ void gc();
+ };
+
+ SP<CWindowHistoryTracker> 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<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};
+}
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 <vector>
+
+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<SWorkspacePreviousData> m_datas;
+ std::vector<SMonitorData> m_monitorDatas;
+
+ void track(PHLWORKSPACE w);
+ void track(PHLMONITOR mon);
+ void gc();
+
+ SMonitorData& dataFor(PHLMONITOR mon);
+ SWorkspacePreviousData& dataFor(PHLWORKSPACE ws);
+ };
+
+ SP<CWorkspaceHistoryTracker> 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<CFocusState> 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<PHLWINDOW>(data);
-
- addWindowToHistory(window);
- });
-
- m_windowClose = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) {
- auto window = std::any_cast<PHLWINDOW>(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<CWLSurfaceResource> surface, bool preserveFocusHistory, bool forceFSCycle) {
+void CFocusState::fullWindowFocus(PHLWINDOW pWindow, SP<CWLSurfaceResource> surface, bool forceFSCycle) {
if (pWindow) {
if (!pWindow->m_workspace)
return;
@@ -93,10 +81,10 @@ void CFocusState::fullWindowFocus(PHLWINDOW pWindow, SP<CWLSurfaceResource> surf
return;
}
- rawWindowFocus(pWindow, surface, preserveFocusHistory);
+ rawWindowFocus(pWindow, surface);
}
-void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP<CWLSurfaceResource> surface, bool preserveFocusHistory) {
+void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP<CWLSurfaceResource> surface) {
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
@@ -164,8 +152,6 @@ void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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<PHLWINDOWREF>& 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<CWLSurfaceResource> surface = nullptr, bool preserveFocusHistory = false, bool forceFSCycle = false);
- void rawWindowFocus(PHLWINDOW w, SP<CWLSurfaceResource> surface = nullptr, bool preserveFocusHistory = false);
- void rawSurfaceFocus(SP<CWLSurfaceResource> s, PHLWINDOW pWindowOwner = nullptr);
- void rawMonitorFocus(PHLMONITOR m);
+ void fullWindowFocus(PHLWINDOW w, SP<CWLSurfaceResource> surface = nullptr, bool forceFSCycle = false);
+ void rawWindowFocus(PHLWINDOW w, SP<CWLSurfaceResource> surface = nullptr);
+ void rawSurfaceFocus(SP<CWLSurfaceResource> s, PHLWINDOW pWindowOwner = nullptr);
+ void rawMonitorFocus(PHLMONITOR m);
- SP<CWLSurfaceResource> surface();
- PHLWINDOW window();
- PHLMONITOR monitor();
- const std::vector<PHLWINDOWREF>& windowHistory();
-
- void addWindowToHistory(PHLWINDOW w);
+ SP<CWLSurfaceResource> surface();
+ PHLWINDOW window();
+ PHLMONITOR monitor();
private:
- void removeWindowFromHistory(PHLWINDOW w);
- void moveWindowToLatestInHistory(PHLWINDOW w);
-
- WP<CWLSurfaceResource> m_focusSurface;
- PHLWINDOWREF m_focusWindow;
- PHLMONITORREF m_focusMonitor;
- std::vector<PHLWINDOWREF> m_windowFocusHistory; // first element is the most recently focused
+ WP<CWLSurfaceResource> m_focusSurface;
+ PHLWINDOWREF m_focusWindow;
+ PHLMONITORREF m_focusMonitor;
- SP<HOOK_CALLBACK_FN> m_windowOpen, m_windowClose;
+ SP<HOOK_CALLBACK_FN> m_windowOpen, m_windowClose;
};
SP<CFocusState> 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<Hyprlang::INT>("input:follow_mouse");
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("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<Hyprlang::INT>("binds:workspace_back_and_forth");
- static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
static auto PWORKSPACECENTERON = CConfigValue<Hyprlang::INT>("binds:workspace_center_on");
static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("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<Hyprlang::INT>("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());