summaryrefslogtreecommitdiff
path: root/src/helpers/Monitor.cpp
diff options
context:
space:
mode:
authorZynix <89567766+alper-han@users.noreply.github.com>2026-03-01 00:49:47 +0300
committerGitHub <noreply@github.com>2026-02-28 21:49:47 +0000
commitc2bed4103c0382de83f5277c5583bb15ae702c2a (patch)
treecc045b65eb9f5ff93ee1e4dbdbbaafbef1fc19d7 /src/helpers/Monitor.cpp
parent82729db330d11d8b39625f04b88bea093f99b33e (diff)
monitor: keep workspace monitor bindings on full reconnect (#13384)
When all monitors disconnect, non-active workspaces could migrate to the wrong output after reconnect. Preserve workspace ownership and re-apply assigned monitor bindings on connect.
Diffstat (limited to 'src/helpers/Monitor.cpp')
-rw-r--r--src/helpers/Monitor.cpp36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index f287bff3..d77a7e76 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -82,7 +82,10 @@ void CMonitor::onConnect(bool noRule) {
m_zoomAnimProgress->setValueAndWarp(0.F);
m_zoomAnimFrameCounter = 0;
- g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
+ g_pEventLoopManager->doLater([] {
+ g_pConfigManager->ensurePersistentWorkspacesPresent();
+ g_pCompositor->ensureWorkspacesOnAssignedMonitors();
+ });
m_listeners.frame = m_output->events.frame.listen([this] {
if (m_frameScheduler)
@@ -290,10 +293,16 @@ void CMonitor::onConnect(bool noRule) {
if (!valid(ws))
continue;
- if (ws->m_lastMonitor == m_name || g_pCompositor->m_monitors.size() == 1 /* avoid lost workspaces on recover */) {
+ const auto CURRENTMON = ws->m_monitor.lock();
+ const bool ORPHANED = !CURRENTMON || std::ranges::none_of(g_pCompositor->m_monitors, [&](const auto& mon) { return mon == CURRENTMON; });
+ const bool RETURNING = ws->m_lastMonitor == m_name;
+ const bool RECOVERY = g_pCompositor->m_monitors.size() == 1 && ORPHANED; // temporarily recover orphaned workspaces
+
+ if (RETURNING || RECOVERY) {
g_pCompositor->moveWorkspaceToMonitor(ws, m_self.lock());
g_pDesktopAnimationManager->startAnimation(ws, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true);
- ws->m_lastMonitor = "";
+ if (RETURNING)
+ ws->m_lastMonitor = "";
}
}
@@ -429,19 +438,24 @@ void CMonitor::onDisconnect(bool destroy) {
m_enabled = false;
m_renderingInitPassed = false;
+ std::vector<PHLWORKSPACE> wspToMove;
+ for (auto const& w : g_pCompositor->getWorkspaces()) {
+ if (w->m_monitor == m_self || !w->m_monitor)
+ wspToMove.emplace_back(w.lock());
+ }
+
+ // Preserve ownership across cascaded monitor disconnects.
+ // The first disconnected monitor "owns" where a workspace should return.
+ for (auto const& w : wspToMove) {
+ if (w && w->m_lastMonitor.empty())
+ w->m_lastMonitor = m_name;
+ }
+
if (BACKUPMON) {
// snap cursor
g_pCompositor->warpCursorTo(BACKUPMON->m_position + BACKUPMON->m_transformedSize / 2.F, true);
- // move workspaces
- std::vector<PHLWORKSPACE> wspToMove;
- for (auto const& w : g_pCompositor->getWorkspaces()) {
- if (w->m_monitor == m_self || !w->m_monitor)
- wspToMove.emplace_back(w.lock());
- }
-
for (auto const& w : wspToMove) {
- w->m_lastMonitor = m_name;
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
g_pDesktopAnimationManager->startAnimation(w, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true);
}