From fa41c8229d46d655bbd3128c0a3844a8d4615c13 Mon Sep 17 00:00:00 2001 From: John Mylchreest Date: Fri, 9 Jan 2026 18:25:37 +0000 Subject: [PATCH] desktop/window: track explicit workspace assignments to prevent X11 configure overwrites (#12850) * fix: track explicit workspace assignments to prevent X11 configure overwrites Instead of only checking for special workspaces, track when workspaces are explicitly assigned via window rules or user actions (movetoworkspace). This prevents onX11ConfigureRequest from overwriting any explicit workspace assignment based on window position. Changes: - Add m_workspaceExplicitlyAssigned flag to CWindow - Set flag when window rules assign workspace - Set flag when user moves window via dispatcher - Check flag in onX11ConfigureRequest instead of just special workspace - Add debug logging for explicit workspace assignments * fix: simplify X11 configure request handling for special workspaces X11 apps send configure requests with positions based on XWayland's monitor layout, which could incorrectly move windows off special workspaces. Skip workspace reassignment when the window is on a special workspace or staying on the same monitor, but always run z-order, fullscreen flag, and damage logic since the configure request may include geometry changes. --- src/desktop/view/Window.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index 4a2d46a9..2559e0c4 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -1499,7 +1499,22 @@ void CWindow::onX11ConfigureRequest(CBox box) { if (!m_workspace || !m_workspace->isVisible()) return; // further things are only for visible windows - m_workspace = g_pCompositor->getMonitorFromVector(m_realPosition->goal() + m_realSize->goal() / 2.f)->m_activeWorkspace; + const auto monitorByRequestedPosition = g_pCompositor->getMonitorFromVector(m_realPosition->goal() + m_realSize->goal() / 2.f); + const auto currentMonitor = m_workspace->m_monitor.lock(); + + Log::logger->log( + Log::DEBUG, + "onX11ConfigureRequest: window '{}' ({:#x}) - workspace '{}' (special={}), currentMonitor='{}', monitorByRequestedPosition='{}', pos={:.0f},{:.0f}, size={:.0f},{:.0f}", + m_title, (uintptr_t)this, m_workspace->m_name, m_workspace->m_isSpecialWorkspace, currentMonitor ? currentMonitor->m_name : "null", + monitorByRequestedPosition ? monitorByRequestedPosition->m_name : "null", m_realPosition->goal().x, m_realPosition->goal().y, m_realSize->goal().x, m_realSize->goal().y); + + // Reassign workspace only when moving to a different monitor and not on a special workspace + // X11 apps send configure requests with positions based on XWayland's monitor layout, such as "0,0", + // which would incorrectly move windows off special workspaces + if (monitorByRequestedPosition && monitorByRequestedPosition != currentMonitor && !m_workspace->m_isSpecialWorkspace) { + Log::logger->log(Log::DEBUG, "onX11ConfigureRequest: reassigning workspace from '{}' to '{}'", m_workspace->m_name, monitorByRequestedPosition->m_activeWorkspace->m_name); + m_workspace = monitorByRequestedPosition->m_activeWorkspace; + } g_pCompositor->changeWindowZOrder(m_self.lock(), true);