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.
This commit is contained in:
John Mylchreest 2026-01-09 18:25:37 +00:00 committed by GitHub
parent 5b1b79c29c
commit fa41c8229d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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);