evidence · 7.9 KiB

README.md

Committed at docs/evidence/card-shell/video-card/README.md. This is what grounds the requirements that cite it.

Open raw source

Video windows are ordinary, closable cards

Headless-QEMU-injected-input evidence only; no physical touch, panel, or mpv/decode proof. See runtime/video’s existing board evidence for actual decode/presentation, and task 4.1 of openspec/changes/video-windows-become-ordinary-cards/tasks.md for the outstanding board re-check.

Root cause

k230-video-software/k230-video-mvx (mpv, launched by nix/video-session.py) were excluded from card_shell ordinary alongside real transient/popup views (nix/card-shell/adapter.c’s “video and transient views stay unmarked” check). A playing video therefore stayed a small 480x270/568x320 floating window: no card, not in the overview, not reachable by the bottom-edge switch gesture, and with no other close control in this touch-only shell. Separately, xdg_toplevel close alone cannot tell video-session.py’s controller “the user closed this” from “the decoder died”, so the MVX fallback path could relaunch a fresh software player right after a close.

Fix

QEMU regression

tests/test_card_shell_video_card.py maps a real k230.card.one fixture and the video app_id k230-video-software (both via card-composition-probe-client, extended to accept the two video app_ids alongside its existing k230.card.one|two|three fixture set) under real cross-built Sway/qemu-riscv64-static with injected touch (SWAY_K230_CARD_TEST_INPUT=1), and proves:

  1. Both reach full 568x1232 ordinary-maximized geometry.
  2. A real touch-first vertical entry swipe (down/motion/motion/up via card_shell test-touch) starting from the focused video card is accepted and settles into the overview (mode==CS_DECK), exactly as it would for any other source.
  3. The video card is a genuine, switchable deck member: card_shell previous/next (the persistent-button route a lateral release resolves to) reaches the other card and back. The video app_id was mapped second in this run (deck index 1), so previous moves toward k230.card.one and next returns to the video card — see the compositor log excerpt below.
  4. card_shell close on the selected video card sends the ordinary xdg_toplevel close (the probe client exits with code 0, matching its default close-accept behavior) and invokes the video-stop helper exactly once with the argument stop.
  5. The other ordinary card is unaffected (still running) and the deck still shows one card afterward.

Verify with (from tests/):

python3 -m unittest test_card_shell_video_card

7 consecutive passes were observed locally (~8-11s each). Two intermediate, now-fixed bugs surfaced while developing this test, kept here because they are real properties of the compositor, not artifacts of the test:

A new debug-scene field, selected_app_id, was added (nix/card-shell/adapter.c’s debug_scene_text) so a test can read the deck’s own current selection directly; Sway’s real seat focus does not move while merely browsing the deck (restore() only reassigns it at CS_RESTORE, i.e. when the overview is actually left), so polling the IPC tree’s "focused" node cannot observe previous/next stepping.

Log excerpt (representative run)

K230_CARD_SHELL_DEBUG_SCENE active=1 ... mode=1 entry_progress=1.0000 ... selected_app_id=k230-video-software   # after entry: video selected
K230_CARD_SHELL_DEBUG_SCENE active=1 ... mode=1 entry_progress=1.0000 ... selected_app_id=k230-video-software   # after `next` (already last index: no-op)
K230_CARD_SHELL_DEBUG_SCENE active=1 ... mode=1 entry_progress=1.0000 ... selected_app_id=k230.card.one         # after `previous`
K230_CARD_SHELL close-request id=5
K230_CARD_SHELL mirror-release id=5 (x2)
K230_CARD_SHELL source-gone id=5
K230_CARD_SHELL unmap id=5
K230_CARD_SHELL_DEBUG_SCENE active=1 ... mode=1 ... ordinary_maximized_cards=1 ... selected_app_id=k230.card.one  # after close: video gone, one card remains
video.poll() = 0   # the probe client exited cleanly on the ordinary xdg_toplevel close

(Full unittest run’s assertions additionally confirm the video-stop helper log contains exactly one line, stop, and that the other card’s process is still running (poll() is None) throughout.)

Narrow proof commands

Limits