Commit graph

159 commits

Author SHA1 Message Date
80e4e288ad feat: keep hidden overlay-preview thumbnails live while held
Hidden tabs live in disabled scene trees, so
wlr_scene_output_send_frame_done() never reaches them and
frame-callback-throttled clients stop committing: only the shown
window's thumbnail tracked live while the rest sat at their last
frame.

Fan frame-done out to every hidden tab window once per output frame
while the overlay is held (overlay_send_hidden_frames after the scene
frame-done in both render_standalone and render_and_present). The
walk covers main plus subsurface trees for both xdg and X11 windows
via window_surface(), and skips the shown window the scene path
already handles.

Gated on --overlay-previews plus overlay_visible, so the steady state
with the menu hidden costs nothing and background clients are not
woken. The existing thumb_capture snapshot and draw-time tree
composite paths are unchanged; they simply receive the commits they
were missing.

Tests: new test_standalone_headless_overlay_previews_hidden_live uses
a hidden --pulse tab and asserts the red thumbnail count swings while
Alt is held. README overlay-previews paragraph updated from freeze to
live-while-held.

Verified: ./build.sh clean; overlay-previews suite 6 passed; full
suite 179 passed with -n4.
2026-10-02 10:24:27 +10:00
b04f6a2826 feat: add --cursor-size flag for standalone pointer size
New --cursor-size N (8..128px, both --cursor-size N and --cursor-size=N forms) sizing the standalone wlr_cursor. Precedence: CLI flag over $XCURSOR_SIZE over the 24px default. Out-of-range, missing or non-numeric values are startup errors (rc 2) naming the flag, matching the existing --start-cmd-index/--tab-groups handling. Nested mode is unaffected (the host draws the pointer there); the flag is silently ignored. Help text, README usage + cursor-shapes section, and a test_cursor_size_flag_errors regression test included. Verified: debug + release builds warning-free; cursor_size + tab-groups flag-error tests pass; --cursor-size 32 boots headless, --cursor-size 999 exits rc 2.
2026-10-01 09:41:36 +10:00
1c1bc5a230 fix: silence sign-compare and format-truncation warnings
Release builds (gcc 16, -O2) warned in three spots; debug builds only showed the first:

- thumb_extent_iter: copy tex->width/height (uint32_t) into int locals
  after the zero guard so all extent math is int<->int.
- dump_path call sites: grow cpath/path buffers 512 -> 1024. Worst
  case is ~535 bytes (dump_dir[512] + kind + seq), so gcc can prove
  no truncation at every inlined site.
- overlay_find_icon_file: skip overlong XDG roots via snprintf return
  checks, fail fast on icon names >1024 chars (can never match a real
  file component), and use %.1024s plus truncation guards in both
  probe loops (worst case ~1.6k < 4096).

No behaviour change on sane inputs: truncated probes previously just
failed access()/fopen(); now they are skipped explicitly.

Verified: full rebuilds of build/ and build-release/ compile with zero
warnings; toplevel_icon_preferred, sigusr1_dumps and
overlay_no_needless_ellipsis pass.
2026-09-30 08:07:39 +10:00
9d1abe2e86 chore: drop unused fields, stale frame flag and duplicate decls
Remove dead code found by read-only audit of kick.c:

- struct kick_window.transient: never read or written, only the
  declaration and generic comments mentioned it.
- struct kick_server.idle_inhibit_destroy: never wired; per-inhibitor
  teardown uses handle_idle_inhibitor_destroy via wl_container_of.
- server.panel_pid: write-only (set in launch_panel, never read);
  keep the [panel] log using the local pid instead.
- static bool frame_pending: write-only global shadowing
  server.output->frame_pending, which is what the main loops actually
  poll alongside needs_frame. Drop the global and its four writes;
  keep handle_output_frame as a documented no-op so the output frame
  listener wiring is unchanged.
- Deduplicate forward declarations: tab_index (keep grouped decl) and
  handle_xs_{associate,commit,surface_map} (keep fuller block).
- Drop empty #if HAVE_XWAYLAND/#endif around the plain Xwayland
  comment above launch_client.

Verified with ./build.sh (only pre-existing sign-compare warnings
in thumb_extent_iter). No behavioural change intended.
2026-09-30 07:55:57 +10:00
498ee6db35 fix: simplify shutdown teardown, lock/inhibit ordering, small input gaps
Shutdown/teardown now reuses remove_tab instead of an open-coded free
loop, closing listener/thumb/MRU/timer gaps with less code; remove_tab
also destroys foreign-toplevel handles, and shutdown removes the full
standalone pointer listener set including gestures.

Key handling: delete the session-locked early return that swallowed
lock-screen typing (grabs stay swallowed by their chord handlers,
passive keys now forward; overlay gated centrally), and move Ctrl+Alt+Q
quit above the shortcuts inhibitor so VT switch and quit stay live
under inhibition (pure reorder).

Input: swallow pointer/touch during quit-confirm as well as overlay,
reset idle on scroll in both axis paths, and guard close_timer against
double-arm. Net fewer lines; all 176 smoke tests pass.
2026-09-29 23:15:44 +10:00
28d5df8d52 feat: show selected window title as header row in preview overlay
Preview menus open with a full-width header naming the active tab's current window (icon plus ellipsized title). Full width keeps menu sizing independent of the selection, so moving the highlight never resizes anything; thumbnail fill-share accounts for the header block within the existing margins. Taps on the header are swallowed.
2026-09-29 07:12:04 +10:00
d47cb4ad03 feat: size overlay preview thumbnails to the menu, capped at quarter screen height
Preview rows divide the content-sized menu (centered, 50px top/bottom margins) instead of using a fixed triple-title height, with each thumbnail capped at a quarter of the screen height. Measure, draw and hit-test share one metrics helper; snapshot size follows a cache with a legacy fallback. Adds a menu-band regression test.
2026-09-28 11:38:16 +10:00
38a17401d1 fix: composite overlay thumbnails from live textures for subsurface windows
Firefox paints into subsurfaces while its main surface stays transparent, so the single-buffer snapshot saw only black. Windows with subsurface content now composite at overlay-draw time from each live surface texture (which outlives current.buffer), while plain windows keep the legacy snapshot path. Adds wltest --subsurface repro mode and a regression test.
2026-09-27 18:22:07 +10:00
8b8137684a fix: route dma-buf straight to GPU thumbnails without CPU probing
Probing every committed buffer with wlr_buffer_begin_data_ptr_access
first can stall on GPU fences at 60Hz, visibly slowing GPU clients
like alacritty when --overlay-previews is on. Check
wlr_buffer_get_dmabuf (a cheap attribute read with no mapping or
sync) first and lock dma-bufs directly for GPU import; only
non-dma-buf buffers go through the CPU snapshot path.
2026-09-27 12:54:46 +10:00
ca9b5ece2c feat: supersampled box-averaged overlay preview snapshots
Snapshot thumbnails at 2x display size with box-averaged
downscaling instead of nearest-neighbor sampling, so window
content (especially terminal text) survives the shrink as
shapes rather than speckle. The GPU bilinear draw stage is
unchanged and now downsamples real detail. Solid colors
average to themselves, so existing color assertions hold.
2026-09-27 10:54:29 +10:00
a7fe1f294d feat: make overlay previews last-appeared instead of live
Drop the ~15fps frame-done tick that woke hidden windows while
the preview overlay was held. Hidden clients now freeze on their
own (no scene frame callbacks), so their thumbnails sit at the
last-shown frame; the shown window keeps its thumbnail live
through its normal commits. Spontaneous hidden commits (a
window mapping mid-hold) still refresh via the unchanged
capture path.

Removes the preview timer, tree walk and arm/disarm logic, the
pulse smoke test that needed tick-driven hidden frames, and
rewrites the README/help wording to last-appeared semantics.
wltest --pulse stays for manual QA.
2026-09-27 08:28:46 +10:00
a9e5f3dcad feat: add --overlay-previews live window thumbnails
Adds a --overlay-previews flag that switches the hold-Alt tab
overlay from icon+title rows to icon plus a small live view of
each window (three times as tall as a title row, no captions).
Tabs with no mapped window keep their command-line text row.

Thumbnails stay live while the overlay is held: hidden windows
get no scene frame callbacks, so a ~15fps tick paces them with
frame-done (disarmed on release; the plain title list never
wakes background clients). Each commit is routed to its fresh
source -- a CPU snapshot for SHM attaches, a locked dma-buf
import for GPU clients, or the surface's own texture for
in-place SHM updates -- and hidden commits force a repaint.

Also adds a wltest --pulse MS mode (alternating color/black on
frame callbacks) as a deterministic live source, three smoke
tests (appear on open, map mid-hold, pulse flip), and README
docs.
2026-09-27 07:07:19 +10:00
2b8560dd7c fix: keep colour emoji in overlay titles 2026-09-23 19:28:30 +10:00
31f413ff9f fix: advertise a render node as the dmabuf main device
On split display/render platforms (vc4 display + v3d render) the
GLES2 renderer resolves to the display node, which has no 3D engine
-- and wlroots then advertises that node as the dmabuf main device,
so Mesa clients try to render there and fall back to llvmpipe (mpv
goes software, drops hundreds of frames).  Discover a real render
node under /dev/dri and override the advertised main device with it;
rendering, allocation and scanout paths are untouched, and a missing
node falls back to the previous renderer-derived behavior.
2026-09-23 13:25:19 +10:00
78285ab581 fix: order cursor above overlay above content on the plane path
Park the hardware cursor plane while the overlay is held and paint
the themed cursor image into the plane buffer after the menu, so the
stack is cursor, overlay, content by construction on every backend:
no cursor layer exists for the menu layer to trade planes with, and
the menu buffer carries its own cursor wherever it lands.  On the
composite path re-add software cursors after the menu pass (a no-op
while a hardware cursor plane is active).

Extend the VT test with kernel-side placement (debugfs crtc-pos and
normalized-zpos must match the logged box on top) and a single-snapshot
cursor-above-menu order check.
2026-09-23 12:24:19 +10:00
33a5f67c50 refactor: paint held overlay at render time, drop poll machinery
Delete the content hash, painted-tracking, loop poll checks and
composite-next cover: the render paths already paint the overlay on
every rendered frame while held, so change detection was pure
overhead -- and polling from the frame handler wedged dispatch at
100% CPU.  Input bindings that mutate the visible menu (tab reorder,
member move, Alt+Shift+T) end in whole-damage plus redraw like any
other keybinding; everything else rides pre-existing commit, damage
and transition flows.  Keeps the persistent plane layer, probe with
sticky fallback, cursor parking during holds, and the per-frame
plane verdict log.
2026-09-23 11:44:28 +10:00
9ea77fde6e fix: harden standalone overlay plane path on real DRM
Replace the per-frame overlay layer churn with one persistent layer
per output (NULL buffer parks it), so libliftoff allocations settle
instead of re-solving around a fresh layer object every frame.

Repaint the held overlay from a per-frame content hash checked in the
main-loop bodies: any drift schedules a frame, clean walks cost one
cheap string pass.  Deliberately not from the output frame handler --
scheduling there re-emits the same event via idle and wedges the loop
at 100% CPU with dead stdin (caught via gdb).  Drop all scattered
explicit overlay refresh calls; the confirm-quit modal stays on its
explicit damage path.

Cover transient plane rejects with one composite frame then retry the
plane; lock software cursors while the overlay is held on DRM so the
menu layer can never trade planes with the cursor across re-solves.
Log the plane verdict and box (WxH+X+Y) every plane frame as the
off-process handle for VT verification.

Add tests/test_vt_plane.py: foot + Alt-held probe + Alt+Shift+T
alacritty on the real DRM backend, asserting the layer stays accepted
and the menu FB sits topmost at the logged geometry (libdrm plane
reads plus debugfs crtc-pos/zpos), with cursor warps and held-key
repeats churning the allocation.
2026-09-23 10:07:00 +10:00
137e4d0568 feat: present standalone overlay on a hardware plane, repaint via per-frame hash poll
On DRM standalone outputs the Alt tab list / confirm-quit modal is
scanned out on a hardware plane via wlr_output_layer (libliftoff), so
the primary buffer stays untouched and direct scanout of the focused
client keeps running underneath. Plane capability is probed once per
output from the first overlay commit and forced via
WLR_DRM_FORCE_LIBLIFTOFF; KICK_OVERLAY_PLANE=0 keeps the composite
fallback. Unlock the plane buffer only after commit, destroy the
per-frame layer after state finish, and recompute the attach-render
lock from capability on output recreate.

Overlay freshness no longer depends on scattered explicit refresh
calls: while held, each frame decision point hashes what the overlay
would draw (rows, titles, highlight, icons) and repaints on drift.
The confirm-quit modal stays on its explicit damage path.

Adds test_alt_shift_t_refreshes_held_overlay.
2026-09-23 05:53:48 +10:00
df65452f62 fix: pace nested presents, size clients from the canvas
Coalesce nested renders while a host present is outstanding (send
frame-done only) instead of burning a full scene build plus GPU blit
per hold-repeat tick; flush clients after every nested render like the
standalone loop; size new/maximized windows and the layer layout from
the synchronously-updated host canvas rather than the lazily-committed
output object; warn when nesting in another kick with the same Alt
prefix; add debug-only render-stage timing.
2026-09-21 13:18:41 +10:00
3ef9285525 fix: flush clients after render in standalone loop
A render queues frame-done (and other) events for clients; without a
flush before blocking in poll they sat in the connection until the
next wakeup (e.g. the headless 60Hz timer ~16ms later), visibly
slowing every standalone client -- including a nested kick, whose
swaps pace on frame-done. The nested loop already flushes every
iteration; mirror that here.

Also log the per-frame [diag] buffer line in render_standalone for
parity with the nested path (debug level only).
2026-09-20 20:09:03 +10:00
a4bef1a0d4 revert: drop KICK_WHEEL_TICKS tick accumulation
Reverts 01fd76e. Tested against the real jittery hardware it was meant
to steady and it did not help, so out it goes rather than carrying a
knob nobody can tune into working. Overlay wheel cycling returns to
one step per discrete tick; the smooth accumulator is untouched.

This reverts both the compositor change and its test plus the
_nested_session extra_env knob, which nothing else uses.
2026-09-18 06:31:31 +10:00
01fd76e1ce feat: steady jittery wheels with KICK_WHEEL_TICKS
A bouncy old wheel emits a burst of discrete ticks per physical notch,
and each tick stepped one overlay tab, so the selection jumped around.
Discrete ticks now accumulate toward a per-step threshold with net
remainders (a +2/-1 burst leaves +1 instead of jumping), mirroring the
smooth-scroll accumulator: deliberate flicks still skip multiple tabs.

The threshold is KICK_WHEEL_TICKS, read per event like
KICK_REPEAT_DELAY_MS; unset or invalid means 1, today's
one-notch-per-step, so good hardware sees no change. It only affects
overlay cycling, never client scrolling, and the leftover fraction
resets when the overlay hides. The smooth 15px threshold is untouched.

Covered by test_overlay_wheel_ticks_env, which spawns with
KICK_WHEEL_TICKS=3 (via a new _nested_session extra_env knob) and
proves two ticks step nowhere while three step exactly once; it fails
on unpatched code.
2026-09-17 13:48:53 +10:00
3a6fdd4fd4 fix: normalize libinput wheel scale so standalone overlay cycling works
One wheel notch in standalone did nothing with the overlay up: libinput
reports discrete ticks scaled by WLR_POINTER_AXIS_DISCRETE_STEP (x120),
so a single notch ran cycle_tab 120 times -- an even number of wraps on
two tabs, netting zero visible movement while still swallowing the
event. The standalone axis handler now divides by the macro before
calling overlay_handle_axis; the client forward path stays raw since
the wlroots seat divides it back itself. Nested was never affected
(its discrete values already arrive in wire units).

Proven by test_standalone_overlay_wheel_libinput_scale, which drives
one notch through the real standalone handler via a new wltest
--virtual-axis mode and asserts exactly one step (it fails with 120
steps without the fix). wltest also grows the missing
axis_source/stop/discrete pointer handlers, without which libwayland
aborts any test client forwarded a scroll event, plus axis lines in
--pointer-out.
2026-09-17 13:33:31 +10:00
0b9012cd6f feat: cycle overlay tabs with the mouse wheel
Rolling the wheel while the overlay is up now steps through tabs
exactly like Alt+Up/Down: wheel down goes to the next tab, wheel up
to the previous one, wrapping at the ends, previewed live and
committed when Alt is released. Notched wheels step one tab per tick;
smooth touchpad-style scroll accumulates to 15px per step. Horizontal
scroll still goes to clients, and with the overlay down nothing
changes.

Swallowed vertical scroll never reaches clients (both the nested and
standalone axis paths share one overlay_handle_axis gate); wltest
grows axis_source/stop/discrete handlers so forwarded scroll no
longer aborts test clients, plus axis lines in --pointer-out.
2026-09-17 12:33:00 +10:00
a4e5633a27 feat: select overlay windows with the mouse cursor
Moving the cursor over an overlay row now previews that window, the
same as dragging a finger across it; sliding off every row keeps the
last preview. Clicks while the overlay is up do nothing and never
reach clients, and releasing Alt commits the preview.
2026-09-16 22:04:37 +10:00
d91cc8ba8d feat: drag across overlay retargets touch selection 2026-09-16 21:36:57 +10:00
0d65efdd49 feat: select overlay windows by touchscreen tap 2026-09-16 21:22:50 +10:00
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
67fd2038b2 feat: kick-pi Pi session wrapper and activation environment refresh 2026-09-13 23:44:04 +10:00
c82954cf7d fix: nested Alt+F11 toggles the shown entry, not the chrome 2026-09-13 18:38:02 +10:00
f829156000 fix: size fullscreen entries to the output on every layout 2026-09-13 13:12:57 +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
a2b7802ec1 fix: three startup/session crashers exposed by eager hosts and real use
tabs/mru lists init before host_init (sync configure walked garbage); EGL init keeps configured host size (swapchain desync abort); overlay sentinel bump snapshots size (shrank 1px/call to zero, then aborted). Adds motion-burst regression test.
2026-09-12 07:53:02 +10:00
5be0db56f6 fix: make prefix+F11 toggle clients fullscreen in standalone mode 2026-09-11 21:59:44 +10:00
4d57dc29bd fix: silence xwayland/xwm noise when quiet via WLR_SILENT 2026-09-11 11:22:42 +10:00
abd8cf640a fix: hide panels when fullscreen so tabs take whole output 2026-09-11 11:03:35 +10:00
f4cd5f7f92 fix: break sweep loop after tab removal; asan-gate defaults 2026-09-11 09:12:58 +10:00
6601e7801e revert: drop unreachable claim-time graceful close, document why 2026-09-11 08:43:17 +10:00
16c5ed58e5 test: locked abs-pointer pin, rogue second lock surface; fix wltest abs gating 2026-09-11 08:37:27 +10:00
21d686df5d fix: drop stale overlay icon texture on re-resolve 2026-09-11 08:10:01 +10:00
8a69b99ae5 fix: guard output size reads against VT-loss teardown 2026-09-11 08:04:05 +10:00
650ca3ba50 fix: clamp absolute pointer motion to active constraint 2026-09-11 07:57:18 +10:00
4b32697f2b fix: clipboard rebind/finish races, x11 scene leaks, or focus, lock surface 2026-09-11 07:51:05 +10:00