Commit graph

37 commits

Author SHA1 Message Date
6b955a2322 render the overlay through one wlr pass in both modes; drop the host-GL overlay path 2026-08-24 09:58:22 +10:00
7bd5cd7dbd unify overlay rendering: one shared layout behind host-GL and wlr-pass backends 2026-08-24 09:11:15 +10:00
ff8a5bc23b auto-detect standalone mode when launched from a Linux virtual console 2026-08-24 08:51:51 +10:00
d13af828b8 draw the overlay backdrop edge-to-edge with rim strokes; repaint fully while shown 2026-08-24 08:30:23 +10:00
8373192d48 tighten overlay spacing: 8px row gap and 8px visible gap between title chips 2026-08-24 07:51:36 +10:00
9cd117e12b restore the grey background behind each overlay title 2026-08-24 07:43:10 +10:00
62ac013df2 refresh the overlay when a window's title or app_id changes
title and app_id arrive as protocol events with no pixel damage, so the
overlay (which reads them live) never repainted while held -- a tab going
from black to content kept showing the command until the menu was closed
and reopened. subscribe to the xdg/x11 set_title and set_app_id signals
(and refresh on map) and repaint in place when the overlay is visible.
2026-08-23 23:06:45 +10:00
c7b5cf0dad show the launch command for still-black overlay tabs
a tab whose window has not opened yet has no mapped members, so its
overlay row drew nothing and showed a blank title. draw the launch
command instead, sized into the panel (which now measures and counts
pending rows) and truncated to the row width if it would overflow.
2026-08-23 22:38:11 +10:00
8edf196981 add a dark-grey background behind each overlay title with row spacing
each window title now sits in its own grey box matching the blue
highlight size, lightened so it separates from the panel, and rows are
spaced so the boxes no longer touch.
2026-08-23 22:16:10 +10:00
bf8252d7f4 widen the gap between member titles in the overlay
double the per-member spacing so stacked windows read as separate items.
2026-08-22 23:39:11 +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
bff05c197f restore the last-focused window when returning to a tab
set_active_app used to discard the tab's focus_member when leaving it,
so coming back always re-focused the newest mapped member instead of the
window the user was last on. keep the pointer on leave and restore it on
enter (falling back to the newest member only if it is no longer mapped).
2026-08-22 23:29:17 +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
884167bbb6 run Xwayland permissively instead of sharing the host Xauthority 2026-08-22 12:13:33 +10:00
aab41f286e make the tab's main surface an ordinary member of its window stack 2026-08-22 10:47:47 +10:00
753b37ee7e add Alt+ backtick to cycle a tab's stacked windows backward 2026-08-22 08:19:08 +10:00
1ef4e4423c draw only the current window of a stacked tab 2026-08-22 07:57:59 +10:00
9d3afadcf1 list key bindings in a Keys section of the -h output 2026-08-21 19:14:19 +10:00
d0851b1ad7 reformat -h output into sections with aligned options table 2026-08-21 19:05:49 +10:00
9e8e2208c3 explain dead startup commands on stderr instead of exiting silently 2026-08-21 13:10:56 +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
613cbe5d19 flush nested-client messages before blocking in the event loop
The clipboard bridge queues a data-control send to the nested client
while dispatching the host side, but the nested loop then blocked in
poll() before wl_display_flush_clients ran. With an idle server loop the
queued message sat unsent for seconds, so host-side wl-paste never
received the payload (the nested client gave up and the socket broke,
seen as EPIPE). Flush clients right after the host dispatch, before the
blocking poll. Also add DEBUG-gated tracing for the clipboard bridge
paths (host/data-control source sends, offer echoes, inner source
lifecycle) used to diagnose the stall.
2026-08-21 07:43:45 +10:00
548d6da88e draw window decorations via libdecor so GNOME windows move and resize
The host window previously asked for server-side decoration; Mutter
forces client-side, so the window had no frame at all and could not be
dragged or resized.  Hand the window to libdecor: it negotiates a
server-side bar when the host offers one and otherwise draws its own
titlebar with move/resize/close buttons (GNOME).
2026-08-20 21:22:25 +10:00
be8f7ec666 defer output resize to render time: one atomic modeset+frame commit per resized frame 2026-08-20 12:40:38 +10:00
3a0fc2c88a render live during headless resize: skip mid-flip guard only on headless output 2026-08-20 12:01:55 +10:00
6cc68edc85 render only on damage and never mid page flip; SIGUSR1 dumps wake idle loop via self-pipe 2026-08-20 10:49:27 +10:00
651f8adcc0 close mirrored-primary pipe fd and prefetch host primary text
Host-primary pastes into the nested seat used to hang waiting for EOF:
bridge_inner_primary_source_send forwarded the demander's fd to the host via
data-control receive but never closed it, so opposite-end reads blocked until
the compositor closed it elsewhere (wlroots only does that for its own
client_source_send).  Close the fd after the direct receive, and eagerly
prefetch the mirrored text/plain payload in a separate buffer so the common
paste is served synchronously without an async fd round-trip.

wltest gains --primary-demand-expect <file> <text> so a nested test can wait
for a specific payload: the live host may already hold its own primary at
boot, which kick faithfully mirrors first, and wlroots only sends offers to
the focused client on the seat.  The new test crowns the demander tab before
the host writes its primary via wl-copy --primary.
2026-08-19 23:09:41 +10:00
ed9f54fb23 bridge primary selection to the host over data-control
Mirror the nested seat's zwp_primary_selection_v1 into the host via the
existing wlr-data-control v2 device (same pipe the clipboard uses), so a
middle-click inside a terminal publishes its primary to the host and the
host's own primary selection shows up in the nested tabs.

- host->nested: a real primary_selection offer is mirrored into the nested
  seat as a wlr_primary_selection_source whose send pulls from the host
  offer's fd; our own publish is tagged as an echo and swallowed (with the
  same NULL-before-echo guard the clipboard already uses).
- nested->host: a nested set publishes a fresh data-control source offered
  with the client's mimes; host middle-click requests are served straight
  from the originating nested client.
- guarded by the bound data-control version (v1 hosts get no primary
  channel, flagged in the init log); the wl_data_device fallback stays
  primary-less as documented.
- wltest --primary-set/--primary-demand now trace the offer/send path.
- new nested-mode smoke test exercises the round-trip and asserts the
  bridge publishes exactly once (no echo loop); suites now 57 passed.
2026-08-19 21:47:29 +10:00
f1d92afe19 implement primary selection v1
Advertises zwp_primary_selection_v1 so text editors can publish and
middle-click-paste without a full clipboard roundtrip.  The device-manager
global hooks the seat; the request_set_primary_selection handler installs
the source on the seat (wlroots only emits the request), and the seat's
focus-change/set fan-out delivers the offer to the keyboard-focused tab's
device, mirroring the clipboard path.  No host bridging: the selection
stays within hosted tabs for now.

wltest gains --primary-set <text> and --primary-demand <file>.  The setter
defers its set_selection until a seat-granted serial arrives (wlroots
rejects serials it never handed out), the demander pulls the payload over a
pipe polling both the pipe and the display socket (the compositor forwards
the fd to the owning tab, whose reply arrives with no display event of
ours).  The smoke test cycles between the two tabs so the setter gets a
serial and the demander is refocused to flush the offer, then verifies the
payload lands in the file.
2026-08-19 19:36:56 +10:00
3eda7016e6 implement pointer constraints and relative pointer
Adds zwp_pointer_constraints_v1 and zwp_relative_pointer_v1 so games and
creative apps can grab the cursor and get raw relative motion.  The
focused surface's constraint is activated/deactivated on seat pointer
focus change; LOCKED pins the pointer to its activation position and
CONFINED clamps it to the constraint region (empty region = the whole
surface), applied through wlr_cursor_warp so the rendered arrow follows.
Relative deltas are forwarded from the real input paths: native
standalone motion sends the raw delta, nested mode derives it from
consecutive host positions.

meson generates the pointer-constraints protocol header (the system
wlroots header quotes it) and the wltest client stacks.  wltest gains
--constrain locked|confined plus --confine-rect, and two smoke tests
verify the cursor stays pinned under LOCKED and clamped to the region
under CONFINED.
2026-08-19 18:49:35 +10:00
ea05f25383 advertise presentation-time, xdg-output and viewporter globals
Clients relied on these to run at their best and fell back otherwise:
wp_presentation gives frame pacing feedback, zxdg_output_manager_v1
logical output geometry for newer toolkits, wp_viewporter lets video
clients scale buffers instead of reallocating.  All three are passive
wlroots globals.  The output layout now exists in both modes so the
nested host-window output is part of it; without that, a client's
get_xdg_output request hit wlr_xdg_output_v1.c's layout_output assert
and aborted the compositor.  wltest gains --globals-out to dump the
advertised interface list (CLI-tab stdout is /dev/null'd by kick), and
a smoke test asserts the new globals are advertised.
2026-08-19 16:47:58 +10:00
96b0942903 overlay: skip zero-sized glyphs in the standalone wlr pass
A glyph with an empty bitmap (the space character reports 0x0 from
FreeType, and too-wide glyphs are skipped at atlas build, leaving
pw/ph at 0) was fed to wlr_render_pass_add_texture with an empty src
and dst box.  wlr_render_texture_options_get_src_box/get_dst_box treat
an empty box as 'use the whole texture', so the entire 16x6 ASCII atlas
was rasterized into the tab row at the space's pen position -- the
onscreen-keyboard graphic seen over 'About galculator'.  Mirror the
nested GL path (draw_texture_rect, which early-returns on src_w/src_h
<= 0) and only emit a quad when the glyph bitmap is non-empty.
2026-08-19 15:57:01 +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
Renamed from tabbed-wlroots.c (Browse further)