From 457617b5a31f70ea63e1fcc0729f29e4a9e6b486 Mon Sep 17 00:00:00 2001 From: Skidam <67871298+Skidamek@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:29:12 +0100 Subject: [PATCH] xwayland: normalize OR geometry to logical coords with force_zero_scaling (#13359) Fixes X11 popups, tooltips, and menus showing black boxes on scaled monitors with xwayland:force_zero_scaling = 1 #13334 --- src/desktop/view/Window.cpp | 25 ++++++++++--------- .../default/DefaultFloatingAlgorithm.cpp | 8 +----- src/layout/target/WindowTarget.cpp | 9 +++++++ 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index 5660cda6..137d79bd 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -2111,8 +2111,11 @@ void CWindow::mapWindow() { if (m_workspace) m_workspace->updateWindows(); - if (PMONITOR && isX11OverrideRedirect()) - m_X11SurfaceScaledBy = PMONITOR->m_scale; + if (PMONITOR && isX11OverrideRedirect()) { + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + if (*PXWLFORCESCALEZERO) + m_X11SurfaceScaledBy = PMONITOR->m_scale; + } } void CWindow::unmapWindow() { @@ -2413,21 +2416,19 @@ void CWindow::unmanagedSetGeometry() { const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(m_xwaylandSurface->m_geometry.pos()); - if (abs(std::floor(POS.x) - LOGICALPOS.x) > 2 || abs(std::floor(POS.y) - LOGICALPOS.y) > 2 || abs(std::floor(SIZ.x) - m_xwaylandSurface->m_geometry.width) > 2 || - abs(std::floor(SIZ.y) - m_xwaylandSurface->m_geometry.height) > 2) { + const auto PMONITOR = m_monitor.lock(); + const auto XWLSCALE = (*PXWLFORCESCALEZERO && PMONITOR) ? PMONITOR->m_scale : 1.0; + const auto LOGICALGEOSIZE = m_xwaylandSurface->m_geometry.size() / XWLSCALE; + + if (abs(std::floor(POS.x) - LOGICALPOS.x) > 2 || abs(std::floor(POS.y) - LOGICALPOS.y) > 2 || abs(std::floor(SIZ.x) - LOGICALGEOSIZE.x) > 2 || + abs(std::floor(SIZ.y) - LOGICALGEOSIZE.y) > 2) { Log::logger->log(Log::DEBUG, "Unmanaged window {} requests geometry update to {:j} {:j}", m_self.lock(), LOGICALPOS, m_xwaylandSurface->m_geometry.size()); g_pHyprRenderer->damageWindow(m_self.lock()); m_realPosition->setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y)); - if (abs(std::floor(SIZ.x) - m_xwaylandSurface->m_geometry.w) > 2 || abs(std::floor(SIZ.y) - m_xwaylandSurface->m_geometry.h) > 2) - m_realSize->setValueAndWarp(m_xwaylandSurface->m_geometry.size()); - - if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = m_monitor.lock(); PMONITOR) { - m_realSize->setValueAndWarp(m_realSize->goal() / PMONITOR->m_scale); - } - } + if (abs(std::floor(SIZ.x) - LOGICALGEOSIZE.x) > 2 || abs(std::floor(SIZ.y) - LOGICALGEOSIZE.y) > 2) + m_realSize->setValueAndWarp(LOGICALGEOSIZE); m_position = m_realPosition->goal(); m_size = m_realSize->goal(); diff --git a/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp b/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp index cbf0f8c0..1fe3b068 100644 --- a/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp +++ b/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp @@ -102,13 +102,7 @@ void CDefaultFloatingAlgorithm::newTarget(SP target) { // TODO: not very OOP, is it? if (const auto WTARGET = dynamicPointerCast(target); WTARGET) { - static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - - const auto PWINDOW = WTARGET->window(); - const auto PMONITOR = WTARGET->space()->workspace()->m_monitor.lock(); - - if (*PXWLFORCESCALEZERO && PWINDOW->m_isX11) - *PWINDOW->m_realSize = PWINDOW->m_realSize->goal() / PMONITOR->m_scale; + const auto PWINDOW = WTARGET->window(); if (PWINDOW->m_X11DoesntWantBorders || (PWINDOW->m_isX11 && PWINDOW->isX11OverrideRedirect())) { PWINDOW->m_realPosition->warp(); diff --git a/src/layout/target/WindowTarget.cpp b/src/layout/target/WindowTarget.cpp index f19ba7ea..05c328af 100644 --- a/src/layout/target/WindowTarget.cpp +++ b/src/layout/target/WindowTarget.cpp @@ -266,6 +266,12 @@ std::expected CWindowTarget::desiredGeomet return std::unexpected(GEOMETRY_NO_DESIRED); } + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + const auto toLogical = [&](SGeometryRequested& req) { + if (m_window->m_isX11 && *PXWLFORCESCALEZERO && PMONITOR) + req.size /= PMONITOR->m_scale; + }; + if (DESIRED_GEOM.width <= 2 || DESIRED_GEOM.height <= 2) { const auto SURFACE = m_window->wlSurface()->resource(); @@ -273,6 +279,7 @@ std::expected CWindowTarget::desiredGeomet // center on mon and call it a day requested.pos.reset(); requested.size = clampSizeForDesired(SURFACE->m_current.size); + toLogical(requested); return requested; } @@ -285,6 +292,7 @@ std::expected CWindowTarget::desiredGeomet if (m_window->m_xwaylandSurface->m_geometry.x != 0 && m_window->m_xwaylandSurface->m_geometry.y != 0) { requested.size = SIZE; requested.pos = g_pXWaylandManager->xwaylandToWaylandCoords(m_window->m_xwaylandSurface->m_geometry.pos()); + toLogical(requested); return requested; } } @@ -318,6 +326,7 @@ std::expected CWindowTarget::desiredGeomet if (DESIRED_GEOM.w <= 2 || DESIRED_GEOM.h <= 2) return std::unexpected(GEOMETRY_NO_DESIRED); + toLogical(requested); return requested; }