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.
This commit is contained in:
parent
82729db330
commit
c2bed4103c
3 changed files with 47 additions and 11 deletions
|
|
@ -3067,6 +3067,27 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspace
|
|||
}
|
||||
}
|
||||
|
||||
void CCompositor::ensureWorkspacesOnAssignedMonitors() {
|
||||
for (auto const& ws : getWorkspacesCopy()) {
|
||||
if (!valid(ws) || ws->m_isSpecialWorkspace)
|
||||
continue;
|
||||
|
||||
const auto RULE = g_pConfigManager->getWorkspaceRuleFor(ws);
|
||||
if (RULE.monitor.empty())
|
||||
continue;
|
||||
|
||||
const auto PMONITOR = getMonitorFromString(RULE.monitor);
|
||||
if (!PMONITOR)
|
||||
continue;
|
||||
|
||||
if (ws->m_monitor == PMONITOR)
|
||||
continue;
|
||||
|
||||
Log::logger->log(Log::DEBUG, "ensureWorkspacesOnAssignedMonitors: moving workspace {} to {}", ws->m_name, PMONITOR->m_name);
|
||||
moveWorkspaceToMonitor(ws, PMONITOR, true);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<unsigned int> CCompositor::getVTNr() {
|
||||
if (!m_aqBackend->hasSession())
|
||||
return std::nullopt;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ class CCompositor {
|
|||
void updateSuspendedStates();
|
||||
void onNewMonitor(SP<Aquamarine::IOutput> output);
|
||||
void ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules, PHLWORKSPACE pWorkspace = nullptr);
|
||||
void ensureWorkspacesOnAssignedMonitors();
|
||||
std::optional<unsigned int> getVTNr();
|
||||
bool isVRRActiveOnAnyMonitor() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue