Every tab is maximized and kick draws no frames, so new toplevels
are pinned to client-side mode (headerbars keep working) and later
server-side requests are ignored. Pinning happens at map -- set_mode
asserts on a never-committed surface, and decoration-before-commit is
the normal order (calling it in new_toplevel_decoration aborts
wlroots); late binds pin immediately when already initialized.
Adds an xdeco probe (maps one shm-backed toplevel, reports the
configured mode) with a regression test asserting mode=1, tracks it
in build.sh staleness, and covers the global in protocol_globals.
Full suite: 153 passed, 2 skipped.
./test.sh with no -n/-m runs the suite as: (1) non-flaky tests under
-n10 (~25s), (2) flaky-marked tests serially (~35s); either phase
failing fails the run (~60s total vs ~160s serial before). Explicit
-n/-m flags keep the old single-phase passthrough behavior
(./test.sh -n0 forces serial). The -m override in phase 2 restates
'not fuzz' since command-line -m replaces pytest.ini's -m.
Make ./test.sh -n4 work (~47s vs ~156s serial):
- kick.c: KICK_DUMP_DIR env override for frame-dump .ppm paths
(default /tmp); per-boot dump_seq counters no longer collide
across concurrent compositors.
- tests: every spawn gets a unique log file and a per-session dump
directory owned by the Session (close removes the tree instead of
globbing /tmp, which raced parallel workers' live dumps).
- 14 protocol-globals tests share one module-scoped keeper session
via short-lived --globals-out clients instead of 14 boots.
- Two presence-waits converted from fixed sleeps to event waits.
- Harden the fullscreen round-trip: wait for seat keyboard focus
([diag] kbd-enter, new debug line in window_enter) before tapping
F -- map alone does not guarantee enter under load and the tap was
silently dropped.
Serial remains the deterministic gate (documented in test.sh and
README): a few pre-existing timing-sensitive tests can still flake
under parallel load; they pass alone and serially.
Three of the four protocols new in wlroots 0.20 (ext-workspace has no
meaningful mapping onto kick's tab model, so it stays out):
- wl_fixes (core, v1): advertise the global; wlroots serves
destroy_registry itself. Clients like Firefox use it to tear down
registries without tripping protocol errors.
- xdg-toplevel-tag-v1: record each window's tag + translated
description ([tag] log line per change), show 'title [tag]' in the
overlay, and with --tab-groups on stack an unmapped external window
onto the tab whose window carries the same tag (browser-style tag
groups). Tags arriving before claim wait in a pending list keyed by
toplevel; mapped windows never move.
- color-representation-v1: advertise an explicit SDR sRGB set
(premultiplied-electrical alpha, identity coefficients in full
range) rather than the renderer's query, which reports empty on
GLES2; wlroots validates client values against it.
Tests: wltest gains --tag-set/--tag-desc and --color-probe/--color-out
(bind-time listener, since the manager bursts on bind); the globals
test covers all three new globals; new tag, tag-grouping and color
round-trip tests; README documents all three.
The wlr-screencopy unstable protocol is deprecated; its superseding
staging protocols ext-image-copy-capture-v1 and
ext-image-capture-source-v1 ship in wayland-protocols. Migrate:
- advertise wlr_ext_image_copy_capture_manager_v1 and
wlr_ext_output_image_capture_source_manager_v1 instead of the
wlr_screencopy_manager_v1 global (wlroots runs the whole session/frame
flow off the output commit path, so no listener wiring is needed)
- rewrite wltest --screencopy for the new client flow: bind the capture
managers, create an output capture source, open a copy-capture session,
wait for the constraint batch (buffer_size/shm_format/done), then attach
a shm buffer and ask for one frame
- generate the two client stubs from wayland-protocols and drop the
bundled wlr-screencopy-unstable-v1.xml
- update the globals test to the new interface names
Existing wl_data_device-based clipboard bridge code is unaffected.
The wlr-data-control unstable protocol is deprecated; its superseding
staging protocol ext-data-control-v1 ships in wayland-protocols.
Migrate the host-side clipboard/primary bridge to it:
- bind ext_data_control_manager_v1 version 1 instead of zwlr_manager
(ext-data-control v1 always supports primary selection, so the
dc_primary_supported gate is dropped and the registry bind is plain)
- rename all zwlr_data_control_* to ext_data_control_* types/calls
- generate ext-data-control-v1 from wayland-protocols and drop the
bundled wlr-data-control-unstable-v1.xml
- update README and test log-message expectations
wltest --screencopy is unaffected; the screencopy migration is separate.
Prefix+Tab and prefix+1 preview the session's windows most-recently-used
first: each press steps to the next window after the shown one in server.mru
order, wrapping at the bottom, without mutating the stack until the modifier
is released. Releasing after navigating commits the shown window to the
front; a bare hold leaves the order untouched. Focus changes with the
modifier up move the entered window to the front immediately.
Alt+1 is the chord that survives hosts like GNOME, which grab Alt+Tab,
Alt+Esc and Alt+Backtick (the latter via the metacity-era switch_group
default) before a nested compositor ever sees them; Alt+Tab is kept for
hosts that leave it free. Windows join the stack least-recent on allocation
and are removed on teardown; reachable stops mirror cycle_tab (live or
pending-claim, not closing). Holding the chord repeats via the existing
synthesized-repeat machinery.
Tests cover stepping, commit-on-release, the Alt+1 synonym, and hold-to-
repeat.
Advertise zwlr_output_manager_v1 with the single head, published on
setup and re-published from the commit path whenever the size lands
(resizes apply lazily, so the commit -- not the request -- is where
the new size becomes observable).
Client sizes apply standalone through the normal resize path (tabs
reflow, swapchain follows); nested refuses anything but the live
size since the host owns the geometry. Disabling, scale and
transform changes are refused; superseded configs are destroyed
after feedback.
Standalone output_resize now owns the canvas size so client resizes
reach the lazy modeset. wltest gains --output-mgmt; smoke tests
cover the global, head listing, and an 800x600 apply with tab
reflow.
Advertise xdg_toplevel_icon_manager_v1 (28px, the overlay draw size)
and use the largest uploaded buffer as the tab's overlay texture.
The desktop-file guesser stays as the fallback -- and the only source
for X11 windows -- so every window still gets an icon; clearing the
icon drops back to guessing.
wltest gains --icon; smoke tests cover the global and the end-to-end
protocol-icon preference.
Drive the output commit's async-flip flag from the shown surface's
tearing hint (a real tearing flip on DRM; correctly ignored on
headless/nested), with per-object hint tracking that requests a frame
on change. Notify each surface of the output scale at claim so
clients never guess preferred_scale.
wltest gains --tearing and --fractional-out (plus linking the two
protocol stubs it now uses); smoke tests cover the async commit
transition and the notified scale value.
Advertise zwp_pointer_gestures_v1 (v3, with hold) and fan libinput
touchpad gestures out to the client holding seat pointer focus.
The stdin test feed gains swipe/pinch/hold messages driving the same
forwarders in any mode (nested has no host gesture source).
wltest gains --gesture-log plus swipe/pinch/hold feed helpers; smoke
tests cover the global and an exact-value round trip of every gesture
and cancel path.
Advertise xdg_wm_dialog_v1 and mirror each dialog object onto its
window. A modal dialog demands attention: on map (or when set modal
while mapped) its tab is shown and it takes window focus, in both
--tab-groups modes; placement itself is unchanged and session lock
still wins.
wltest gains --dialog-modal/--extra-modal/--extra-delay; smoke tests
cover the global, the background-modal steal with tab-groups on, and
the own-tab steal with tab-groups off.
Advertise zwlr_gamma_control_manager_v1 and commit client ramps to
the single output (reset when the control goes away); other outputs
and failed commits fail the control so clients retry. Outputs with
no LUT (headless/nested) are failed by wlroots itself.
wltest gains a --gamma mode reporting gamma_size/failed; smoke tests
cover the global and the clean headless failure path.
Advertise zwp_text_input_manager_v3 + zwp_input_method_manager_v2 and
relay the focused field to the in-session IME and back (enter/leave on
seat keyboard focus, keyboard-grab forwarding, IME popups above tabs).
Also advertise wp_content_type_manager_v1 (logged on map) and
wp_single_pixel_buffer_manager_v1 (scaled via viewporter).
wltest gains --text-input/--input-method/--content-type/--single-pixel
modes; smoke tests cover globals, the IME round trip, focus follow,
single-pixel rendering and the content-type log line.
libdecor sat on the critical path of every host-window transition even
where it drew nothing: on compositors honoring server-side decorations
(labwc/sway/KDE) it negotiated SSD, then still injected permanent
set_window_geometry hints and batched acks inside its own commit call.
labwc 0.9.8 expires a 100 ms configure deadline under load and answers
"move but keep old size" -- anchoring fullscreen views to stale geometry
forever.
the host window now selects its backend at startup: compositors
advertising zxdg_decoration_manager_v1 get kick-owned xdg_shell objects
with immediate configure acks, an explicit server-side decoration request,
and no geometry hints at all (KICK_LIBDECOR=1 forces the libdecor path);
hosts without the manager -- Mutter/GNOME forces CSD -- keep libdecor
unchanged. this also restores mirrored fullscreen semantics: a client's
fullscreen request again fullscreens the host window in one step.
a client's fullscreen request used to be mirrored onto the host window
via libdecor, but labwc 0.9.8 expires its 100 ms configure deadline under
load and then applies "move but keep old size" permanently -- the
enlarged image anchored at the old origin with black margins. the mirror
is gone: a client's fullscreen now fills kick's output only, leaving the
host window alone. fullscreening the host remains an explicit act
(prefix+F11 or the compositor), and the host-to-clients propagation is
unchanged.
Kick advertised only pointer+keyboard and ignored every touch device, so
clients never saw a touchscreen and taps were silently dropped.
The seat now advertises WL_SEAT_CAPABILITY_TOUCH. Standalone mode wires
libinput touch devices through wlr_cursor with normalized-absolute warping
and delivers via the seat touch API with slot ids preserved (multi-touch).
Nested mode binds wl_touch when the host seat offers the capability,
forwards events through the same coordinate space as the pointer path, and
ends live sequences cleanly on capability loss or host cancel.
The ctl test feed gains CTL_TOUCH so headless tests can inject taps, and
wltest learns --touch-log to record received events; an end-to-end
regression test proves down/motion/up reach the client with correct slot
and coordinates.
clients_set_fullscreen only told each tab's main surface, so members
stacked before a toggle never learned they were fullscreen, and members
that mapped during fullscreen were never released from it. walk each
tab's member list with a member_set_fullscreen helper (mirroring the app
one) and give xdg members the same re-maximize/resize mains get on the
way out; X11 members keep their own geometry. logged as
"members fullscreen=" next to the existing line.
a grabbed prefix+F11 chord flips the host window's fullscreen state via
libdecor; the resulting configure fans out to every tab through the
usual host->clients propagation, exactly like a host-compositor
fullscreen. latched against key repeats and a no-op standalone, where
there is no host window. plain unprefixed F11 still passes through to
clients.
GDK_BACKEND/QT_QPA_PLATFORM forced to wayland stripped toolkits' fallback,
killing X11-only builds like emacs-gtk ('cannot open display' against a
healthy Xwayland). Children now self-select from WAYLAND_DISPLAY/DISPLAY,
and XAUTHORITY is cleared.
Separately, X11 membership decisions moved from window-creation time to
first map: GTK leader windows never map, yet claimed the tab slot at
creation, leaving a permanent black tab while the real frame was demoted
to a stacked member -- and Alt-cycling onto that phantom main member
crashed on wlr_seat_keyboard_notify_enter(NULL). Never-mapped windows now
free silently; keyboard-entry paths guard on live surfaces. New
tests/xleader.c probe (unmapped leader + mapped frame) locks the behaviour
in.
the tab overlay now lists every window of a tab (main plus stack members)
with a per-window icon and title instead of one icon and title per tab, and
highlights only the active window so the overlay cursor can move across all
of a tab's windows. titles are also centered within each row.
A second toplevel from an already-connected client is a sub-window of
that client's tab. tabs (default) keeps today's behavior: its own slot
glued right of the parent. stack never creates a slot: the window rides
above the parent tab's surface as a scene-tree child, sharing its
visibility, holding the keyboard while the tab is shown, and falling
back to the tab's own surface when it closes. Stacked windows are
invisible to cycling and the overlay; closing the tab closes them.
Overlay rows follow what sits on top of the tab: the row title and icon
resolve from the topmost mapped stacked window and revert when it goes,
with a [title] log line per row-title change for observability.
wltest grows an 'X' key that closes its --extra toplevel so the unstack
path is testable.
test_clipboard_nested_to_host and test_clipboard_host_to_nested were
marked flaky because of the bridge stall now fixed; re-enable them in
the default run. Drop the host-colour readback and never-connecting
tests along with their helpers, and mark the primary-selection bridge
test flaky instead. Update the README's flaky-test note.
test_nested_host_primary_to_kick only has a host->nested primary channel
when the host exposes wlr-data-control v2; a focus-based wl_data_device
host (GNOME/mutter) has no primary bridge at all, so on those desktops the
demand-expect tab can never receive the host primary and the test timed
out. Wait for the bridge_init backend decision and skip unless the
data-control v2 backend is in use; the round-trip is still exercised by
./test-headless.sh, whose headless host is kick itself.
Nested clients that switch the pointer cursor's shape now keep a correct
cursor over kick's window: advertise wp_cursor_shape_manager_v1, apply the
requested shape to the compositor cursor in standalone mode, and forward it
to the host pointer in nested mode via a hand-rolled client call (kick stays
a single C file, so the generated client header is not included). Shapes
are cached per tab and reset to default on tab switch so a text cursor never
leaks between apps. Legacy wl_pointer.set_cursor surfaces are not bridged.
The ctl pointer feed now also drives the nested seat directly, so the harness
can give a nested client a pointer enter. wltest gains --cursor-shape and an
explicit flush (wl_display_dispatch does not flush queued requests), plus the
now-required frame handler. New tests cover apply, tab-switch reset, and
nested forwarding; tail of README documents the protocol and its limits.