From 556b3f9bf61088f6ed2ac36e21250e2c07174e89 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Thu, 14 May 2026 12:12:28 +0200 Subject: [PATCH] steamcompmgr: do not forcefully snap focus windows to (0, 0) The compositor already ignores a focus window's X11 origin when computing layer offsets. Fix MouseCursor::paint to match, using origin (0, 0) for the focus window when positioning the cursor. Some games draw a plain background window and another smaller window on top with the actual game contents, which they center by requesting a specific position on screen. Gamescope would force that content window back to (0, 0), only to be requested to move it back to where the game wants it, endlessly, which would result in bad flickering. Such a game is Nobunaga's Ambition: Hadou when played in borderless mode. --- src/steamcompmgr.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 83c2a811ff..51d3c5a67e 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1943,9 +1943,14 @@ void MouseCursor::paint(steamcompmgr_win_t *window, steamcompmgr_win_t *fit, str cursorOffsetX = (currentOutputWidth - sourceWidth * currentScaleRatio_x) / 2.0f; cursorOffsetY = (currentOutputHeight - sourceHeight * currentScaleRatio_y) / 2.0f; - // Actual point on scaled screen where the cursor hotspot should be - scaledX = (winX - window->GetGeometry().nX) * currentScaleRatio_x + cursorOffsetX; - scaledY = (winY - window->GetGeometry().nY) * currentScaleRatio_y + cursorOffsetY; + // Actual point on scaled screen where the cursor hotspot should be. + // Compositing ignores the focused window's X11 origin, so the cursor + // must also ignore it to stay consistent with the composited output. + bool isFocusWindow = (window == m_ctx->focus.focusWindow); + int32_t winOriginX = isFocusWindow ? 0 : window->GetGeometry().nX; + int32_t winOriginY = isFocusWindow ? 0 : window->GetGeometry().nY; + scaledX = (winX - winOriginX) * currentScaleRatio_x + cursorOffsetX; + scaledY = (winY - winOriginY) * currentScaleRatio_y + cursorOffsetY; if ( zoomScaleRatio != 1.0 ) { @@ -3956,9 +3961,6 @@ void xwayland_ctx_t::DetermineAndApplyFocus( const std::vector< steamcompmgr_win ctx->focus.focusWindow->nudged = true; } - if (w->GetGeometry().nX != 0 || w->GetGeometry().nY != 0) - XMoveWindow(ctx->dpy, ctx->focus.focusWindow->xwayland().id, 0, 0); - if ( win_has_game_id( w ) ) { if ( window_is_fullscreen( ctx->focus.focusWindow ) || ctx->force_windows_fullscreen )