fix: window swaps flash the desktop background + redundant alpha re-stamps flicker backdrop materials#1409
Open
KhangHLe wants to merge 1 commit into
Open
fix: window swaps flash the desktop background + redundant alpha re-stamps flicker backdrop materials#1409KhangHLe wants to merge 1 commit into
KhangHLe wants to merge 1 commit into
Conversation
Two independent causes of visible flicker when windows exchange rects: 1. set_transparency re-fired SetLayeredWindowAttributes with unchanged values on every effects pass (e.g. the all-windows pass queued on animation completion), forcing DWM to re-evaluate composition - which visibly blinks system-backdrop materials (Acrylic/Mica) on windows that carry them. Now skipped when the window is already layered at the target alpha. 2. Plain repositions executed as individual SWP_ASYNCWINDOWPOS calls, which land frames apart per-app - so two windows exchanging rects expose the desktop in the vacated slot between the two moves, even with animations and transparency disabled. Plain (non-animated, non-surrogate, steady-state-visible) repositions are now collected during the redraw loop and committed in one atomic DeferWindowPos transaction, mirroring the existing surrogate batch. Single-window cycles keep the historical individual async path. Known residual: a rare flash remains, suspected cross-sync-cycle split of the two moves (needs instrumentation; not fixable by within-cycle batching).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two independent, reproducible sources of visible flicker when tiled windows exchange positions (
move --directionbetween two windows):The desktop flashes in the vacated slot. Each window is repositioned with its own
SetWindowPoscall underSWP_ASYNCWINDOWPOS, so the two moves are queued to each app's own thread and land frames apart — the region one window vacates stays exposed (showing the desktop/background) until the other window's move lands. Reproducible with transparency effects disabled; most visible with two windows of the same size swapping slots.Backdrop materials blink on effect passes.
set_transparencyre-firesSetLayeredWindowAttributeseven when the value is unchanged. A redundant re-stamp isn't free: DWM re-evaluates the window's composition, which visibly flickers system-backdrop materials (Acrylic/Mica) on windows that carry them (e.g. Windows Terminal with acrylic, Firefox with Mica, Explorer). Effects passes re-apply transparency liberally, so any sync that touches effects blinks every glass window on screen.Fix
Atomic repositions: plain repositions (ordinary, steady-state-visible windows — no restore, no DPI fix-up, no minimize/maximize/fullscreen special-casing, no active drag) are collected during the redraw loop and committed in a single
BeginDeferWindowPos/EndDeferWindowPostransaction after it, so all rects land in the same compositor frame. A lone entry keeps the historical individual async path; anything state-special keeps the individualreposition_windowpath unconditionally. On any batch failure it falls back to individual repositions.Idempotent alpha:
set_transparencyreads the current layered attributes first and returns early when the window is already layered at the target alpha.Notes
WindowPosBatchis a small RAII-ish wrapper inwm-platformaround the defer APIs;SWP_ASYNCWINDOWPOSis stripped inside the batch (deferred transactions commit synchronously by design).mainand compile-verified against it.Happy to split into two PRs if preferred.