desktop/workspaceHistory: fix tracking for multiple monitors (#12979)
This commit is contained in:
parent
e0cf88809d
commit
ac9df44788
3 changed files with 110 additions and 50 deletions
|
|
@ -193,6 +193,68 @@ static bool testAsymmetricGaps() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testMultimonBAF() {
|
||||||
|
NLog::log("{}Testing multimon back and forth", Colors::YELLOW);
|
||||||
|
|
||||||
|
OK(getFromSocket("/keyword binds:workspace_back_and_forth 1"));
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch focusmonitor HEADLESS-2"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 1"));
|
||||||
|
|
||||||
|
Tests::spawnKitty();
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch workspace 2"));
|
||||||
|
|
||||||
|
Tests::spawnKitty();
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch focusmonitor HEADLESS-3"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 3"));
|
||||||
|
|
||||||
|
Tests::spawnKitty();
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch workspace 3"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activeworkspace");
|
||||||
|
EXPECT_CONTAINS(str, "workspace ID 2 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch workspace 4"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 4"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activeworkspace");
|
||||||
|
EXPECT_CONTAINS(str, "workspace ID 2 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch workspace 2"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activeworkspace");
|
||||||
|
EXPECT_CONTAINS(str, "workspace ID 4 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch workspace 3"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 3"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activeworkspace");
|
||||||
|
EXPECT_CONTAINS(str, "workspace ID 4 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch workspace 2"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 3"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 1"));
|
||||||
|
OK(getFromSocket("/dispatch workspace 1"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activeworkspace");
|
||||||
|
EXPECT_CONTAINS(str, "workspace ID 3 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Tests::killAllWindows();
|
||||||
|
}
|
||||||
|
|
||||||
static bool test() {
|
static bool test() {
|
||||||
NLog::log("{}Testing workspaces", Colors::GREEN);
|
NLog::log("{}Testing workspaces", Colors::GREEN);
|
||||||
|
|
||||||
|
|
@ -527,13 +589,15 @@ static bool test() {
|
||||||
EXPECT_CONTAINS(str, "class: kitty_B");
|
EXPECT_CONTAINS(str, "class: kitty_B");
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy the headless output
|
|
||||||
OK(getFromSocket("/output remove HEADLESS-3"));
|
|
||||||
|
|
||||||
// kill all
|
// kill all
|
||||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||||
Tests::killAllWindows();
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
testMultimonBAF();
|
||||||
|
|
||||||
|
// destroy the headless output
|
||||||
|
OK(getFromSocket("/output remove HEADLESS-3"));
|
||||||
|
|
||||||
testSpecialWorkspaceFullscreen();
|
testSpecialWorkspaceFullscreen();
|
||||||
|
|
||||||
testAsymmetricGaps();
|
testAsymmetricGaps();
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@
|
||||||
|
|
||||||
#include "../../helpers/Monitor.hpp"
|
#include "../../helpers/Monitor.hpp"
|
||||||
#include "../Workspace.hpp"
|
#include "../Workspace.hpp"
|
||||||
|
#include "../state/FocusState.hpp"
|
||||||
#include "../../managers/HookSystemManager.hpp"
|
#include "../../managers/HookSystemManager.hpp"
|
||||||
|
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
||||||
#include "../../config/ConfigValue.hpp"
|
#include "../../config/ConfigValue.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||||
|
|
||||||
using namespace Desktop;
|
using namespace Desktop;
|
||||||
using namespace Desktop::History;
|
using namespace Desktop::History;
|
||||||
|
|
||||||
|
|
@ -19,22 +23,16 @@ CWorkspaceHistoryTracker::CWorkspaceHistoryTracker() {
|
||||||
track(workspace);
|
track(workspace);
|
||||||
});
|
});
|
||||||
|
|
||||||
static auto P1 = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) {
|
static auto P1 = g_pHookSystem->hookDynamic("focusedMon", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||||
auto mon = std::any_cast<PHLMONITOR>(data);
|
auto mon = std::any_cast<PHLMONITOR>(data);
|
||||||
track(mon);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CWorkspaceHistoryTracker::SMonitorData& CWorkspaceHistoryTracker::dataFor(PHLMONITOR mon) {
|
// This sucks ASS, but we have to do this because switching to a workspace on another mon will trigger a workspace event right afterwards and we don't
|
||||||
for (auto& ref : m_monitorDatas) {
|
// want to remember the workspace that was not visible there
|
||||||
if (ref.monitor != mon)
|
// TODO: do something about this
|
||||||
continue;
|
g_pEventLoopManager->doLater([this, mon = PHLMONITORREF{mon}] {
|
||||||
|
if (mon)
|
||||||
return ref;
|
track(mon->m_activeWorkspace);
|
||||||
}
|
});
|
||||||
|
|
||||||
return m_monitorDatas.emplace_back(SMonitorData{
|
|
||||||
.monitor = mon,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,44 +50,32 @@ CWorkspaceHistoryTracker::SWorkspacePreviousData& CWorkspaceHistoryTracker::data
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorkspaceHistoryTracker::track(PHLWORKSPACE w) {
|
void CWorkspaceHistoryTracker::track(PHLWORKSPACE w) {
|
||||||
if (!w->m_monitor)
|
if (!w || !w->m_monitor || w == m_lastWorkspaceData.workspace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
|
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
|
||||||
|
|
||||||
auto& data = dataFor(w);
|
auto& data = dataFor(w);
|
||||||
auto& monData = dataFor(w->m_monitor.lock());
|
|
||||||
|
|
||||||
if (!monData.workspace) {
|
Hyprutils::Utils::CScopeGuard x([&] { setLastWorkspaceData(w); });
|
||||||
data.previous.reset();
|
|
||||||
data.previousID = WORKSPACE_INVALID;
|
if (m_lastWorkspaceData.workspace == w && !*PALLOWWORKSPACECYCLES)
|
||||||
data.previousName = "";
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
data.previous = m_lastWorkspaceData.workspace;
|
||||||
|
if (m_lastWorkspaceData.workspace) {
|
||||||
|
data.previousName = m_lastWorkspaceData.workspace->m_name;
|
||||||
|
data.previousID = m_lastWorkspaceData.workspace->m_id;
|
||||||
|
data.previousMon = m_lastWorkspaceData.workspace->m_monitor;
|
||||||
|
} else {
|
||||||
|
data.previousName = m_lastWorkspaceData.workspaceName;
|
||||||
|
data.previousID = m_lastWorkspaceData.workspaceID;
|
||||||
|
data.previousMon = m_lastWorkspaceData.monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
void CWorkspaceHistoryTracker::gc() {
|
||||||
std::erase_if(m_datas, [](const auto& e) { return !e.workspace; });
|
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) {
|
const CWorkspaceHistoryTracker::SWorkspacePreviousData* CWorkspaceHistoryTracker::previousWorkspace(PHLWORKSPACE ws) {
|
||||||
|
|
@ -156,3 +142,15 @@ SWorkspaceIDName CWorkspaceHistoryTracker::previousWorkspaceIDName(PHLWORKSPACE
|
||||||
|
|
||||||
return SWorkspaceIDName{.id = DATA->previousID, .name = DATA->previousName, .isAutoIDd = DATA->previousID <= 0};
|
return SWorkspaceIDName{.id = DATA->previousID, .name = DATA->previousName, .isAutoIDd = DATA->previousID <= 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWorkspaceHistoryTracker::setLastWorkspaceData(PHLWORKSPACE w) {
|
||||||
|
if (!w) {
|
||||||
|
m_lastWorkspaceData = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastWorkspaceData.workspace = w;
|
||||||
|
m_lastWorkspaceData.workspaceID = w->m_id;
|
||||||
|
m_lastWorkspaceData.workspaceName = w->m_name;
|
||||||
|
m_lastWorkspaceData.monitor = w->m_monitor;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,21 +32,19 @@ namespace Desktop::History {
|
||||||
SWorkspaceIDName previousWorkspaceIDName(PHLWORKSPACE ws, PHLMONITOR restrict);
|
SWorkspaceIDName previousWorkspaceIDName(PHLWORKSPACE ws, PHLMONITOR restrict);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SMonitorData {
|
struct SLastWorkspaceData {
|
||||||
PHLMONITORREF monitor;
|
PHLMONITORREF monitor;
|
||||||
PHLWORKSPACEREF workspace;
|
PHLWORKSPACEREF workspace;
|
||||||
std::string workspaceName = "";
|
std::string workspaceName = "";
|
||||||
WORKSPACEID workspaceID = WORKSPACE_INVALID;
|
WORKSPACEID workspaceID = WORKSPACE_INVALID;
|
||||||
};
|
} m_lastWorkspaceData;
|
||||||
|
|
||||||
std::vector<SWorkspacePreviousData> m_datas;
|
std::vector<SWorkspacePreviousData> m_datas;
|
||||||
std::vector<SMonitorData> m_monitorDatas;
|
|
||||||
|
|
||||||
void track(PHLWORKSPACE w);
|
void track(PHLWORKSPACE w);
|
||||||
void track(PHLMONITOR mon);
|
|
||||||
void gc();
|
void gc();
|
||||||
|
void setLastWorkspaceData(PHLWORKSPACE w);
|
||||||
|
|
||||||
SMonitorData& dataFor(PHLMONITOR mon);
|
|
||||||
SWorkspacePreviousData& dataFor(PHLWORKSPACE ws);
|
SWorkspacePreviousData& dataFor(PHLWORKSPACE ws);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue