Commit graph

70 commits

Author SHA1 Message Date
57c5cb7912 docs: single-instance panels cannot nest; skip panel test when host owns bus 2026-09-15 23:20:56 +10:00
07ba288b5d feat: --focus-priority favors active window via nice/ionice 2026-09-14 21:33:32 +10:00
0ac7c5c3f6 fix: scrub mode vars from client environments 2026-09-14 11:42:30 +10:00
2a2aa2fbcb feat: standalone autodetect for DM Wayland sessions 2026-09-14 10:58:03 +10:00
6ec0d5f338 revert: drop per-compositor app config shadowing 2026-09-14 09:43:23 +10:00
240c1cea4f feat: per-compositor app config in kick, slim kick-pi 2026-09-14 07:30:04 +10:00
cb362b1519 feat: overlay titles via Pango+Cairo with full Unicode support 2026-09-13 11:59:07 +10:00
94884b1ef2 feat: layout and panels follow the shown entry, not the aggregate 2026-09-13 09:19:21 +10:00
e7df8d5396 feat: per-entry fullscreen, host chrome follows shown clients 2026-09-12 12:20:25 +10:00
5be0db56f6 fix: make prefix+F11 toggle clients fullscreen in standalone mode 2026-09-11 21:59:44 +10:00
6b4418ae4f feat: serve xdg-decoration-v1 pinned client-side
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.
2026-09-10 03:08:18 +10:00
8bdaa970cc feat: advertise alpha-modifier-v1 (passive surface alpha) 2026-09-10 02:30:55 +10:00
21460bcac9 feat: advertise xdg-system-bell-v1 (log rings at info level) 2026-09-09 22:49:32 +10:00
5b871e447b feat: advertise color-management-v1 (SDR sRGB session) 2026-09-09 22:47:44 +10:00
1f295a0580 Revert "test: two-phase default gate -- parallel non-flaky, then serial flaky"
This reverts commit ce19b77ac7.
2026-09-08 18:08:58 +10:00
ce19b77ac7 test: two-phase default gate -- parallel non-flaky, then serial flaky
./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.
2026-09-08 13:49:03 +10:00
7e2bb18a85 test: parallel-safe suite (xdist), shared globals session, KICK_DUMP_DIR
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.
2026-09-08 12:02:02 +10:00
7c77a3beaf feat: implement wl_fixes, xdg-toplevel-tag, color-representation (wlroots 0.20)
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.
2026-09-08 10:22:50 +10:00
ccbc782177 migrate screen capture from wlr-screencopy to ext-image-copy-capture
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.
2026-09-08 06:49:39 +10:00
592a2a036e migrate clipboard bridge from wlr-data-control to ext-data-control
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.
2026-09-08 00:37:52 +10:00
0dc782a5d3 build: target wlroots 0.20, pin fallback to 0.20.2
Rename the text_input/input_method manager events and declare the
host-side cursor-shape interfaces wlroots 0.20 no longer exports
via its headers.
2026-09-07 23:37:45 +10:00
1f35f90a95 Alt+Tab / Alt+1 walks a window-level MRU stack, commits on release
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.
2026-09-06 23:52:03 +10:00
d8164ce315 protocols: expose output-management, honor resizes standalone
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.
2026-09-04 10:52:16 +10:00
fcd3bca53b protocols: prefer xdg-toplevel-icon artwork in the overlay
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.
2026-09-04 10:35:34 +10:00
50a660860d protocols: honor tearing hints and fractional scale
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.
2026-09-04 10:21:30 +10:00
8a71a062ce protocols: forward pointer-gestures swipe/pinch/hold
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.
2026-09-04 10:13:13 +10:00
b189318124 protocols: support xdg-dialog modal toplevels
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.
2026-09-04 10:00:34 +10:00
42853dcc18 protocols: honor wlr-gamma-control for night-light tools
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.
2026-09-04 09:43:04 +10:00
b9194addf4 protocols: input-method relay, content-type, single-pixel
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.
2026-09-04 09:37:13 +10:00
844c88e5bb remove test-headless.sh; de-race fullscreen, cursor, alt-delete, and primary-selection tests against suite-load flakes 2026-09-01 13:37:38 +10:00
c10845f2c1 route the host window through xdg-shell directly on SSD compositors
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.
2026-08-26 18:19:59 +10:00
aafd2de5b7 contain client fullscreen inside kick; decouple from the host window
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.
2026-08-26 10:11:18 +10:00
595e9b95a0 add touchscreen support: nested forwarding and standalone native input
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.
2026-08-25 09:36:17 +10:00
87f25783d9 propagate host fullscreen to stacked tab-group members too
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.
2026-08-24 23:25:31 +10:00
86fe848acd toggle the kick window's fullscreen with prefix+F11
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.
2026-08-24 23:09:43 +10:00
08202dc6c3 fix X11 app startup: no forced toolkit backends; X11 windows join tabs at first map
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.
2026-08-24 10:43:41 +10:00
ff8a5bc23b auto-detect standalone mode when launched from a Linux virtual console 2026-08-24 08:51:51 +10:00
0868571a7f show each window of a tab with its own icon in the overlay
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.
2026-08-22 23:32:03 +10:00
2263d1096a cycle the active tab's windows with Alt+Left / Alt+Right 2026-08-22 22:16:51 +10:00
39329347f6 close the active window with Alt+Delete, not the whole tab 2026-08-22 22:03:34 +10:00
118f5c276a rename --sub-windows to --tab-groups; document process-ancestry grouping 2026-08-22 13:32:04 +10:00
753b37ee7e add Alt+ backtick to cycle a tab's stacked windows backward 2026-08-22 08:19:08 +10:00
05189128df add XWayland support: X11 apps open as tabs beside Wayland clients 2026-08-21 12:37:28 +10:00
2dde2b6510 add --sub-windows tabs|stack: sub-windows can stack on their parent tab
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.
2026-08-21 11:35:21 +10:00
b9d1782938 un-mark fixed clipboard tests and retire dead flaky tests
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.
2026-08-21 07:44:00 +10:00
75735e38f4 mark flaky tests and exclude them from the default run 2026-08-20 21:22:25 +10:00
957f7c5749 skip host->nested primary test without a data-control host
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.
2026-08-20 21:22:25 +10:00
9e9f4e3174 apply and forward cursor-shape-v1 requests, with per-tab cache
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.
2026-08-19 15:08:31 +10:00
3ccae6cbe1 rename project to kick (repo, binary, socket, env) 2026-08-19 11:46:25 +10:00
ac386e6454 run nested tests against a headless host; fix standalone data-control selection 2026-08-19 10:27:43 +10:00