Commit graph

34 commits

Author SHA1 Message Date
8acd384666 Document usage, keybindings, TABBED_LOG/dump semantics; fix F8->F9/F10 comment 2026-08-09 13:02:46 +10:00
6b049debf0 Build with meson; portable wlroots fallback (pinned wrap) + README 2026-08-09 12:46:14 +10:00
ea6fea80d7 Drop legacy tabbed-wayland/tabbed-windows binaries and their Makefile targets 2026-08-09 12:16:14 +10:00
49db6e9834 Remove tab limit: growable apps array (drop MAX_APPS and dead MAX_WIN defines) 2026-08-09 12:15:13 +10:00
18653c9031 Clean up stale Wayland socket on shutdown, crash, and startup 2026-08-09 12:02:21 +10:00
b80871c62c Handle SIGINT (Ctrl-C) like SIGTERM for graceful shutdown 2026-08-09 11:50:40 +10:00
3381193f11 Repeat tab cycling while Ctrl+PageUp/Down is held 2026-08-09 02:53:32 +10:00
b62e4d0386 Route xkbcommon logs through TABBED_LOG; robust host keymap read 2026-08-09 02:28:36 +10:00
3356e503f4 Quiet logging by default via TABBED_LOG; silence client chatter 2026-08-09 02:02:22 +10:00
4fce5e1e72 Disable direct scanout so nested frames composite fully
wlroots was presenting the client's raw buffer straight to the headless
output via direct scanout, bypassing our swapchain, so the host blit
showed a stale/black window (seen with Firefox). Force composition into
the swapchain by setting WLR_SCENE_DISABLE_DIRECT_SCANOUT.

Keep F8/F9, SIGUSR1 and TABBED_AUTODUMP dumps; gate verbose per-frame
diag logging behind TABBED_DEBUG=1.
2026-08-09 01:22:01 +10:00
95b13d29ff Add F11 toggle to fullscreen the host window
Track the host compositor's fullscreen state from the xdg_toplevel
configure states and toggle it with F11 (xdg_toplevel_set_fullscreen /
unset_fullscreen). Passing a NULL output lets the host compositor choose
the current output; the existing resize cascade re-sizes all tabs with
the fullscreen configure.
2026-08-08 19:37:54 +10:00
43bca3dde8 Insert new tabs next to the tab that created them
Instead of appending dialogs/second windows at the far right of the tab
list, insert the new tab immediately after the tab that created it, using
the protocol parent (wlr_xdg_toplevel.parent) first and falling back to
the active tab, then to appending at the far right.
2026-08-08 18:31:52 +10:00
d149a1adf2 Advertise wl_surface at v4 to tolerate legacy client attach offsets
VLC's Wayland vout places video using non-zero wl_surface.attach x/y
offsets, which is a protocol violation on surfaces bound at version 5 or
higher and got the client killed with an invalid_offset error during
resizes. Advertise wl_surface at v4 so those offsets are accepted and
ignored as before the v5 breaking change.
2026-08-08 13:09:43 +10:00
570465c6e6 Pace host presents and add cross-context sync barrier
Gate host presents with the surface's wl_callback so at most one buffer is
outstanding at a time (coalescing bursts via back_dirty), add a glFinish
barrier between the wlr GLES2 renderer context and the host EGL context used
by the blit, and switch the scene clear colour to black after removing the
import-failure present. Keep temporary F8/F9 frame dumps (scene vs. host
back buffer) for grey-band diagnosis.
2026-08-08 12:14:29 +10:00
3d2c627552 Kill client processes on compositor shutdown 2026-08-07 21:23:01 +10:00
3740fed066 Give dialogs/second windows their own tab 2026-08-07 20:31:24 +10:00
0b6a9eef75 Composite popups and fix sub-menu rendering 2026-08-07 19:07:40 +10:00
efecacacb1 Ignore maximize/fullscreen requests before first commit
GTK clients like geany send xdg_toplevel.set_maximized before their
first commit. wlr_xdg_toplevel_set_maximized() schedules a configure,
which asserts the surface is initialized and aborts the compositor.
Guard the request handlers with the surface's initialized flag and let
the commit handler apply maximization once the client has committed.
2026-08-07 11:15:53 +10:00
77cbf96ff2 Warn when host keymap fails to parse
Host keyboard keymaps occasionally fail to compile with xkbcommon, which
was silent and left clients on the fallback layout. Log a clear message
so it is diagnosable instead of confusing.
2026-08-07 11:02:09 +10:00
33956c7a18 Detach app listeners and switch tabs on client close
wlroots emits xdg_toplevel events.destroy with NULL data and asserts
every toplevel/surface event listener list is empty afterwards. We kept
8 listeners attached and never removed them, so closing any client
tripped destroy_xdg_toplevel's assertion and took down the whole
compositor. The active-tab check also compared against NULL data, so the
switch/exit path never ran.

Capture the destroyed toplevel before nulling it, remove all attached
listeners so wlroots' destroy assertions pass, activate the next live tab
when the focused one closes, and only exit when the last tab is closed.
2026-08-07 10:53:42 +10:00
729b72002f Keep all mapped clients maximized on host resize
output_resize only resized the active toplevel, so inactive tabs kept
their old (smaller) size and were still small when switched to. Loop
over every mapped client, maximizing and sizing them all whenever the
host window changes size, so tab switching needs no per-tab relayout.
2026-08-07 10:38:52 +10:00
ec3ec08e11 Request server-side decorations from the host compositor
The nested window is an xdg_toplevel client inside labwc, but tabbed-
wlroots never bound xdg-decoration-unstable-v1, so labwc added no title
bar. Generate the client protocol (wayland-scanner), register it in the
Makefile, and after creating the host toplevel request SERVER_SIDE mode
so labwc draws a real host title bar above the nested content. Adds an
informational configure listener that reports the effective mode.
2026-08-07 10:32:11 +10:00
b7faf9ec91 Crop CSD titlebar gutter instead of terminal bottom row
For clients (kitty/foot) that reserve a titlebar gutter above their
content but never paint it, that area showed as a dark bar while their
content sat low enough that the bottom row/cursor was pushed out the
output edge. Shift such clients up by the gutter so the dark bar is
cropped away instead of the terminal's bottom. Clients with no gutter
(geometry.y >= 0, e.g. the shm test client) are left untouched.
2026-08-07 10:27:55 +10:00
b59840bc49 Disable direct scanout and import shm swapchain buffers
On a headless backend wlr_allocator_autocreate yields a shm allocator,
so the scene swapchain buffer is shm, not a dmabuf. import_scene_buffer
only handled dmabufs, so the composited scene never reached the host
window. kitty only worked via accidental direct scanout of its own
dmabuf buffer.

Add a full-output background scene_rect so the render list always has
more than one entry (disabling single-buffer direct scanout), and add a
CPU-read fallback to import_scene_buffer for non-dmabuf buffers. Now the
whole window composites through for both shm and dmabuf clients, with
content reaching the exact bottom edge.
2026-08-07 07:48:27 +10:00
927054d7bc Dump host window on SIGUSR1 instead of periodic dmabuf frame dumps
Periodic dumps filled /tmp with 3MB PPMs and stopped working once the
swapchain stopped being ARGB8888 dmabufs. Capture the presented host
EGL window with glReadPixels instead, triggered on demand with
kill -USR1 <pid>.
2026-08-06 22:20:34 +10:00
097b5a732d Add wlroots-0.19 tabbed compositor with working seat keyboard routing
Nested compositor running on the wlroots 0.19 headless backend with a
host EGL window on labwc. Clients are always maximized to the host
content area and keyboard input is delivered via the seat (tinywl
pattern). Closing the last tab closes the host window and exits.
2026-08-06 22:17:40 +10:00
ca40ec06ad Composite client sub-surfaces (CSD) in the EGL and shm render paths
Track sub-surface roles and positions via the wl_subcompositor so foot's
client-side decorations render: toplevel -> titlebar -> controls. Draw the
active surface's buffer at the window-geometry offset and its sub-surfaces
recursively on top, clipping to the window. Sub-surface commits of the active
tab trigger redraws but never resize the host window.
2026-08-06 18:43:35 +10:00
786f7904b5 Fix foot window shrink by sizing host window only once 2026-08-06 12:22:22 +10:00
5d08c7d342 Rename tabby prefix to tabbed everywhere 2026-08-06 12:21:00 +10:00
202baf4914 Use per-instance pid-based Wayland socket name 2026-08-06 11:23:26 +10:00
7c6d28995c Fix deferred buffer release and window geometry in tabbed-wayland 2026-08-06 11:19:39 +10:00
eb0f5c05ef Add tabbed-windows nested compositor with EGL/dmabuf client support 2026-08-06 11:19:35 +10:00
3ae1a7320a Fix blank client frames and frame-callback stall
Blit client buffers from their top-left origin instead of honoring
set_window_geometry offsets: clients like foot set a geometry that
extends above the buffer (CSD shadow, geom_y < 0), which made the
source row pointer start before the buffer and produced a blank
frame. Buffers are now copied 1:1 from origin, capped to canvas.

Also dispatch wl_callback.done on the first configure commit so
frame-throttled clients (foot) don't stall waiting for it.
2026-08-05 12:49:07 +10:00
1206ab41db Tabby: C Wayland compositor with xdg-shell tabbed windows
Single-file Wayland compositor presenting client surfaces as tabs in a
GTK3 window. Implements wl_compositor, wl_shm/shared memory, xdg-shell,
wl_seat/keyboard/pointer, and launches apps from tab-commands.

- Validate client buffer geometry against pool size at create_buffer and
  commit time to prevent out-of-bounds reads from malformed buffers.
- Release client shm buffers immediately after deep-copying pixels,
  replacing the fragile foot/GTK3 deferred-release state machine.
2026-08-05 11:52:07 +10:00