Skip to content

fix(x11): correct XDBE swap presentation on Xwayland (font thickening + frame repeat)#2369

Draft
tmineno wants to merge 4 commits into
brndnmtthws:mainfrom
tmineno:fix/xdbe-back-buffer-clear
Draft

fix(x11): correct XDBE swap presentation on Xwayland (font thickening + frame repeat)#2369
tmineno wants to merge 4 commits into
brndnmtthws:mainfrom
tmineno:fix/xdbe-back-buffer-clear

Conversation

@tmineno
Copy link
Copy Markdown
Contributor

@tmineno tmineno commented May 23, 2026

Two related fixes for XDBE double-buffering under Xwayland (and drivers where XdbeBackground is unreliable). Found while running conky as an X11 client on GNOME/Mutter + NVIDIA.

1. Back buffer not cleared -> fonts thicken (ec9bc11)

In the XDBE path clear_text() is a no-op and the back buffer is only ever reset via the XdbeBackground swap action. Some drivers don't honor it (notably under Xwayland and certain NVIDIA setups); the back buffer then keeps the previous frame, so antialiased glyphs blend on top of themselves and fonts appear to thicken over time -- most visibly when other windows overlap conky and trigger extra redraws.

Fix: clear the back buffer explicitly with XFillRectangle after the swap, mirroring the existing XPMDB path.

2. Deferred swap -> momentary frame repeat (b3e0409)

The swap was left in the X output buffer and flushed lazily. Under Xwayland the compositor can coalesce/reorder it with later requests and momentarily re-present the previous frame -- a visible "frame repeat" (e.g. a clock's seconds bouncing back, 40 -> 39 -> 40, at the boundary).

Fix: XSync after the swap so the server processes it before conky proceeds, giving a clean, ordered present. A plain XFlush only queues the request and is not enough (verified empirically: XFlush still bounces, XSync does not).

Blast radius

  • X11 output with double_buffer = true on XDBE builds only. XPMDB builds, Wayland output, and double_buffer = false are unchanged.
  • On drivers where XdbeBackground already works, the explicit clear is a redundant reset (identical output).

Testing

Verified on Xwayland + Mutter (GNOME) + NVIDIA with an ARGB (semi-transparent) own_window_colour and double_buffer = true: no font thickening on overlap, no frame-repeat at the second boundary.

XdbeBackground is supposed to reset the back buffer to the window
background after each swap, but some drivers (notably under Xwayland
and certain NVIDIA setups) ignore it. The back buffer then keeps the
previous frame, so antialiased glyphs blend onto themselves and fonts
appear to thicken — most visibly when other windows overlap conky and
trigger extra redraws. Clear the back buffer explicitly with
XFillRectangle after the swap, mirroring the XPMDB path.
@netlify
Copy link
Copy Markdown

netlify Bot commented May 23, 2026

Deploy Preview for conkyweb canceled.

Name Link
🔨 Latest commit 9105dbb
🔍 Latest deploy log https://app.netlify.com/projects/conkyweb/deploys/6a12a73dfc2f2d0008887e2c

@github-actions github-actions Bot added sources PR modifies project sources display: x11 related to X11 backend labels May 23, 2026
@tmineno tmineno marked this pull request as ready for review May 23, 2026 14:46
A swap left in the X output buffer is flushed lazily (on the next request that
forces a flush). Under Xwayland the compositor can then coalesce/reorder it
with later requests and momentarily re-present the previous frame -- a visible
"frame repeat", e.g. a clock's seconds briefly bouncing back (40 -> 39 -> 40)
right at the boundary.

XSync after the swap blocks until the server has processed it, yielding a
clean, ordered present. A plain XFlush only queues the request and is not
enough (verified: XFlush still bounces, XSync does not).
@tmineno tmineno changed the title fix(x11): clear XDBE back buffer explicitly to stop font thickening fix(x11): correct XDBE swap presentation on Xwayland (font thickening + frame repeat) May 23, 2026
@tmineno tmineno marked this pull request as draft May 23, 2026 16:19
@Caellian Caellian added bug related to incorrect existing implementation of some functionality env: xwayland only present when XWayland is used labels May 23, 2026
@Caellian
Copy link
Copy Markdown
Collaborator

How does XPMDB work for you?

I'm asking because XPMDB path is much closer to how Wayland side works and also how most GUI toolkits handled double buffering on X11 (not relying on Xdbe ext - even though now it's always provided). I was hoping to remove one or the other and make it so that X11 just uses Cairo if it's included the same way Wayland does (pipeline unification), after Cairo rendering backend is up-to-speed of course.

The XPMDB present had two Xwayland-specific issues that together caused an
intermittent whole-window blank flicker (background-only for a frame, even
when idle):

1. The XCopyArea was flushed with XFlush, which only queues the request, so
   the compositor could pick it up mid-update. XSync after the copy blocks
   until the server has processed it, giving a clean, ordered present -- the
   same fix already applied to the XDBE path.

2. The XCopyArea inherited the GC's dirty-region clip and so refreshed only
   the changed area, whereas XdbeSwapBuffers always presents the whole
   window. Under Xwayland the window's backing buffer does not reliably
   persist the previous frame between presents, so a partial copy leaves the
   rest blank. Drop the clip before the copy so the full window is always
   presented; the XPMDB path redraws the full text rect every frame, so
   clearing the whole back buffer afterward stays safe.
@tmineno
Copy link
Copy Markdown
Contributor Author

tmineno commented May 24, 2026

@Caellian Tested it — built with -DBUILD_XDBE=OFF to exercise use_xpmdb on the same box (Xwayland + Mutter + NVIDIA, ARGB own_window_colour, double_buffer = true).

  • Font thickening: none. XPMDB already clears the back buffer every frame (the path fix fix imap message count updates #1 mirrors), so nothing accumulates.
  • Flicker: XPMDB isn't immune — I had to (1) XSync instead of XFlush after the present, and (2) drop the dirty-region clip so the whole window is copied each frame (XDBE's swap already presents the whole window; a partial copy leaves the rest of Xwayland's reallocated buffer blank). With both, it's solid.

XPMDB's copy-to-window model maps better onto the Wayland/Cairo path, so +1 on consolidating there. I've added both fixes to the XPMDB path in this PR.

@tmineno
Copy link
Copy Markdown
Contributor Author

tmineno commented May 24, 2026

Correction to "solid": longer soak shows a rare residual blank-frame flicker, and it's on the XDBE path too (the shipped build with both fixes) — so not XPMDB-specific. Whole-window present and XSync cut the rate; dropping the server-side background didn't help further, and none of it fully eliminated the flicker; two different present paths (Xdbe swap vs pixmap copy) showing the same symptom puts the cause below X11, in Xwayland's async surface-commit → compositor-present. (Couldn't cross-check via native Wayland output — out_to_wayland hard-requires wlr-layer-shell, which Mutter doesn't implement.) So XPMDB ≈ XDBE here; fully eliminating it likely needs the Wayland/Cairo present path.

@Caellian
Copy link
Copy Markdown
Collaborator

Here's a patch for Mutter that adds wlr-layer-shell. I don't use it, so I never tested it - only that it compiles and looks somewhat reasonable (Claude output).

If you go with it, match the version you already have on your system and apply the patch on top. It might yield better or worse results depending on how extensively you're using conky (cairo backend is not complete).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug related to incorrect existing implementation of some functionality display: x11 related to X11 backend env: xwayland only present when XWayland is used sources PR modifies project sources

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants