# Card-composition pinned source audit Generated by `python3 tools/audit-card-composition-sources.py --flake . --output docs/research/card-composition-source-audit.md`. ## Resolved inputs * `.#shell-compositor` derivation: `/nix/store/cjwd6s14flmqlrxmiqh951d9jj1n50a6-sway-unwrapped-riscv64-unknown-linux-gnu-1.12.drv` * `.#touch-launcher` derivation: `/nix/store/1n8haskvgqhvhci6xxqsglwvhnakzjd0-k230-touch-launcher.drv` * Sway 1.12 source from the compositor derivation's `src` environment field: `/nix/store/2j7grygxd5da5r214vzz3y8b54rr739k-source` * Installed wlroots headers: `/nix/store/dsxkjg3whpq9xvy5kd5k7mddq927a2l6-wlroots-0.20.2/include/wlroots-0.20`. The resolved package is the same flake attribute used by the `k230` NixOS configuration. This audit does not infer an ABI from a host Sway executable. ## Client/protocol boundary `nix/touch-launcher/default.nix:13-20` generates only layer-shell and xdg-shell client protocols and links `wayland-client`. In `nix/touch-launcher/touch-launcher.c:68-75,765-789`, the launcher binds `wl_compositor`, `wl_shm`, `wl_seat`, and `zwlr_layer_shell_v1`, creates its own overlay surface, and requests non-interactive keyboard focus. Its `wl_touch` listener (`:723-761`) receives touch only after Sway has selected that client surface. It has neither a compositor-owned `wlr_surface` reference for another client nor a global pre-routing touch hook. The current client route can therefore retain metadata/launcher controls but cannot produce live application cards, global drag, or authoritative focus restoration. ## Sway/wlroots boundary The pinned Sway source allocates a `scene_tree` and `content_tree` per `sway_view` in `sway/tree/view.c:77-95`, assigns the view scene descriptor at `:85`, and positions content through `wlr_scene_node_set_position` at `:1043-1047`. It destroys the scene node during view teardown at `:135-139`. It already keeps a saved-surface tree and clones scene-buffer references at `:1245-1289`; this is evidence of a compositor-owned lifetime boundary, not a license to expose client buffers to another process. Sway routes touch through seat operations: `sway/input/seat.c:1577-1600` dispatches down/motion/up/cancel to the active `seatop_impl`, and the default operation resolves a container then calls `seat_set_focus_container` and `seatop_begin_down` in `sway/input/seatop_default.c:242-271`. Focus helpers are in `sway/input/seat.c:1255-1299`; `view_close` dispatches the existing view implementation at `sway/tree/view.c:547-551`. These are patch points for an opt-in Sway-owned card state machine. wlroots 0.20's installed `wlr/types/wlr_scene.h:306-351,708-715` exposes node positioning, input hit-testing, and an XDG-surface scene subtree. It has no transform for a whole scene subtree: `wlr_scene_buffer_set_dest_size` at `:535-543` scales an individual buffer only. Sway's existing `view_save_buffer` at `sway/tree/view.c:1245-1289` clones scene-buffer references and disables live content, so it is a lifetime example but not a live-card transform. The selected probe must prove identical scale and translated coordinates for every live content/subsurface buffer across commits, or stop without calling cropped or static output a card. Pinned Sway also exposes more protocols than the current launcher binds: `sway/server.c:469-476` creates foreign-toplevel managers, `:502-517` creates export-dmabuf/screencopy/image-copy managers, and `:555-563` creates foreign-toplevel image-capture sources. A request is served from a separate `view->image_capture_scene` using Sway's allocator and renderer (`:230-242`), not by sharing the live scene node. A client could enumerate/activate/close and receive copied images, but would compose copies in its overlay, would not own Sway's focus or pre-routing touch, and has no demonstrated frame/presentation synchronization with copied content. That route cannot meet the coherent live surface/global drag/focus contract at an unmeasured Pixman cost. Its `wlr/types/wlr_presentation_time.h:64-106` says a compositor must record sampling/texturing and send presentation feedback only when it has that evidence. The probe must log those calls separately from a frame callback. ## Result The source evidence selects a narrow, opt-in Sway patch for the next probe because it can keep app surfaces, input, focus, close dispatch, and presentation accounting under one owner. It does **not** prove coherent live subtree scaling, board operation, or product card UX. Those remain strict selected-route probe gates.