| Age | Commit message (Collapse) | Author | Files | Lines |
|
|
|
Regression I introduced two commits ago, reported live: "I can click close
where the button would normally be and it does close, but it is still
invisible."
The gate that stops an empty frame being drawn before a client paints asked
the renderer, from inside the render loop, whether a window's surface had a
buffer attached right now - and treated "no" as "do not draw". That
question is only meaningful for a native xdg-shell toplevel. An XWayland
window's surface state does not describe it the same way, so the answer came
back no on every frame and the window was never drawn again, while srdwm's
own hit-testing carried on working perfectly: an invisible window that still
takes clicks, which is a worse failure than the empty frame it was meant to
prevent.
Inverted to the fail-safe direction. `new_managed_window` - the one path
that creates a native toplevel - puts the window into
`awaiting_first_buffer`, and `commit` takes it out on the first commit that
carries a buffer. The render and capture paths test that set and nothing
else. A window is now hidden only when srdwm itself put it there, so no
window whose plumbing works differently can be hidden by a lookup that did
not apply to it: the XWayland map path never touches the set, and neither
can anything else.
The buffer question still gets asked, but only in `commit`, about a surface
it was just handed, where it is the right question.
Verified both halves: an ordinary spawn still shows no frame before content
(26 captured frames with content, 0 without), and the only way into the set
is one line in one function.
|
|
Reported as "before a window spawns, the border corners look funny".
A toplevel is placed, sized and decorated the moment its role is created,
which is well before the client draws. srdwm was rendering it from that
moment, so what appeared first was an empty frame: border, titlebar and
shadow standing around bare desktop, at the guessed 800x600 placeholder
size, with nothing inside. When the real buffer arrived the frame snapped
to the real size.
Measured in a nested session, capturing a cold terminal's spawn with grim:
four consecutive captured frames spanning 540ms showed a complete red
border with zero client content inside it, at 642px outer height, which
then settled at 610 - a jump of exactly one TITLEBAR_HEIGHT. After this
change the same capture has no such frame at all: every frame that shows a
border shows content in it, and the height does not change afterward.
Two parts:
- Nothing is drawn for a window that has never committed a buffer. All
five paths that draw a frame agree on this - both udev render loops
(Pixman and GPU), the winit render loop, and both screencopy paths, so a
screenshot cannot show a frame the screen does not.
- The open-slide starts at the first commit that carries a buffer rather
than at role creation. A cold terminal took ~800ms to paint, long enough
for the whole tween to finish against the empty frame, so the window
simply appeared, already at rest, with no animation at all. It now
animates where it can actually be seen.
The answer latches once true (windows_shown_once), so a window that has
legitimately shown something is never hidden again by this however its
buffer state changes. A window that cannot be resolved to a surface counts
as drawable, deliberately: this hides a window only on positive evidence
that it has never drawn, so nothing whose surface plumbing works
differently - an XWayland window - can be hidden by a lookup that did
not apply to it.
Same shape, and the same reason, as sync_layer_visibility's own has_buffer
branch, which layer surfaces have had all along.
533 tests pass, clippy clean.
|
|
Root-caused "windows spawn small and square, not remembering placement or
size": new_managed_window hardcoded a fresh toplevel's geometry to 800x632
before the client had said anything about its own preferred size, and
sync_geometry forced that guess onto the client's very first
xdg_toplevel::configure unconditionally. Per xdg-shell, size: None on that
first configure is how every mainstream compositor lets a client pick its
own natural size instead; this one never did, so every app converged on
the same placeholder rectangle regardless of what it would have chosen.
Window::size_is_provisional marks a size that really was just the guess
(not a remembered geometry, a rule's explicit geometry action, or a
maximize/phone-mode fill, none of which are guesses). sync_geometry sends
size: None for such a window's first configure; a new adopt_provisional_size,
called from the commit handler, adopts the client's own real first size
into Window::geometry the moment it commits one, clamping only position so
a bigger-than-guessed window can't hang off its monitor's edge.
Live-verified in a nested compositor: a zenity dialog now renders at its
own compact natural size instead of being stretched to the old guess.
|
|
Safety commit before reconciling this worktree with main, which has
diverged with its own separate fixes today. Nothing here is reviewed
or curated yet - this exists purely so none of this work can be lost
to a git operation, disk issue, or worktree cleanup while that
reconciliation happens.
|