https://bugs.kde.org/show_bug.cgi?id=526999
Bug ID: 526999
Summary: wlr-layer-shell: a commit that changes buffer size and
anchors/margins is painted for one frame at the old
position
Classification: Plasma
Product: kwin
Version First unspecified
Reported In:
Platform: Other
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: wayland-generic
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
When a wlr-layer-shell client changes its buffer size together with its
anchors/margins/size in a single wl_surface.commit, KWin applies the new buffer
at the surface's OLD position immediately and moves the surface to its new
position only later, when the deferred rearrange runs. If the output repaints
in between, one frame shows the new buffer at the old position, so the content
visibly jumps for one frame.
How I was able to repro:
1. A layer surface on the overlay layer, exclusive zone 0, anchored top|left
with margins (715, 0, 0, 1256), showing a 560x298 buffer
2. In ONE commit: set_anchor(top|bottom|left|right), set_size(0, 0),
set_margin(0, 0, 0, 0), and attach a 1816x1013 buffer whose content is drawn
for the new position (the old content at 1256,715 inside the buffer)
3. Then the reverse, in ONE commit: set_anchor(top|left), set_size(560, 298),
set_margin(847, 0, 0, 1526), attach a 560x298 buffer
Repeat a few dozen times
Actual:
The window's frameGeometry changes in two steps: first a resize to the new
buffer size at the old position, then, one event-loop pass later, the move to
the new position. A frame callback (wl_callback.done) sent between the two
steps shows a frame was painted in that state. In step 2 the content appears at
2512,1430 (twice its offset), in step 3 at 0,0, for one frame. On a 60 Hz
output this happened in roughly 1-5% of such commits
Excerpt (WAYLAND_DEBUG=server plus a KWin script printing the window's
frameGeometry on change, same stream):
[07:05:33.411708] wl_surface#64.attach(wl_buffer#78, 0, 0)
[07:05:33.411712] wl_surface#64.commit()
js: geometry x=1256 y=715 w=1816 h=1013 <- new size at the old position
[07:05:33.411846] wl_display#1.sync(new id wl_callback#47)
[07:05:33.412018] -> wl_callback#69.done(167057409) <- frame painted in
that state
[07:05:33.412041] -> zwlr_layer_surface_v1#67.configure(16, 3072, 1728)
js: geometry x=0 y=0 w=1816 h=1013 <- moved
Expected:
The buffer and the layer state of one commit take effect together, as
wlr-layer-shell's double-buffered state implies: no frame shows the new buffer
at the old position.
System info:
Operating System: CachyOS, Linux 7.2.9-2-cachyos
KDE Plasma Version: 6.7.5
KDE Frameworks Version: 6.30.0
Qt Version: 6.12.0
Graphics Platform: Wayland. Also reproduced with kwin_wayland --virtual
Additional info:
Reading KWin v6.7.5:
- LayerShellV1Window::handleSizeChanged (src/layershellv1window.cpp:298-301)
calls updateGeometry(RectF(pos(), clientSizeToFrameSize(surface()->size())))
synchronously from SurfaceInterface::sizeChanged, keeping the old pos()
- Anchor, margin and desired-size changes only call scheduleRearrange()
(src/layershellv1window.cpp:68-77, 98-101), which restarts a single-shot 0 ms
timer (src/workspace.cpp:311-316, 2416-2419); the new position comes from
LayerShellV1Integration::rearrange() and place() when it fires
(src/layershellv1integration.cpp:86-135, 209-215)
- Nothing holds the output's repaint while a rearrange is pending
Workaround I was able to find: keep the layer surface's size and position
constant while it is visible
--
You are receiving this mail because:
You are watching all bug changes.