diff options
| author | sl0p <sl0p@sl0p.foo> | 2026-08-13 22:26:02 +0200 |
|---|---|---|
| committer | sl0p <sl0p@sl0p.foo> | 2026-08-13 22:26:02 +0200 |
| commit | 34fcd16e59e3087e9bf84ebce4e05d439eea9198 (patch) | |
| tree | e07b9dfc235e3a0b67047d59a9c521c6e98a28ae /src/sl0ptty.h | |
| parent | sl0ptty: input decoder + per-pane re-encode (diff) | |
| download | slosh-34fcd16e59e3087e9bf84ebce4e05d439eea9198.tar.gz slosh-34fcd16e59e3087e9bf84ebce4e05d439eea9198.tar.xz slosh-34fcd16e59e3087e9bf84ebce4e05d439eea9198.zip | |
sl0ptty: M0.5 — the headless driver and the harness everything rests on
--script runs the whole compositor with no tty: commands in (send, raw,
settle, resize, snapshot, alive), composited screen out as JSON — rows of
text, style runs, cursor, and the hit list.
Styles are emitted as runs rather than per-cell objects, because a test wants
'columns 0..5 of row 0 are bold red', not 1920 objects.
The hit list is empty until M1 paints something clickable, but the type, the
JSON, and hit_test() exist now: one geometry, established before there is
anything to get wrong.
Also fixes two host-policy defaults found by the cursor never appearing.
lib-vt is a VT library, not a terminal, so it starts with DECTCEM (mode 25)
off and grapheme clustering (2027) off. Both are now set via MODE_DEFAULT, so
they survive RIS.
tests/harness.py + tests/test_screen.py: 19 checks over composition, styling,
wide chars/clusters, scrollback, resize and the full input round trip —
including the kitty/legacy re-encoding matrix, which no longer needs a pty.
make test is now 2.4s for 59 checks; make test-live keeps the four that
genuinely need a tty.
Diffstat (limited to 'src/sl0ptty.h')
| -rw-r--r-- | src/sl0ptty.h | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/src/sl0ptty.h b/src/sl0ptty.h index c71ec9e..962de66 100644 --- a/src/sl0ptty.h +++ b/src/sl0ptty.h @@ -38,11 +38,31 @@ typedef struct { color_t fg, bg; } cell_t; +/* One geometry (DESIGN.md): every painted interactive element records its rect + * here as it is painted, and a click is a lookup. Drawing and hit-testing + * cannot disagree because there is only one of them. */ +typedef struct { + uint16_t x, y, w, h; + char action[48]; +} hit_t; + +typedef struct { + hit_t *items; + size_t len, cap; +} hitlist_t; + +void hit_reset(hitlist_t *hl); +void hit_add(hitlist_t *hl, uint16_t x, uint16_t y, uint16_t w, uint16_t h, + const char *action); +/* The action at a point, or NULL. Later entries win: painted last is on top. */ +const char *hit_test(const hitlist_t *hl, uint16_t x, uint16_t y); + typedef struct { uint16_t cols, rows; cell_t *cur; /* what we want on screen */ cell_t *prev; /* what the terminal last received */ bool force_full; + hitlist_t hits; /* where the real cursor goes after a flush */ bool cursor_visible; @@ -64,6 +84,8 @@ void screen_put_utf8(screen_t *s, uint16_t x, uint16_t y, const char *txt, void screen_flush(screen_t *s, int fd); /* Plain-text dump of the composited screen; caller frees. (headless tests) */ char *screen_dump(screen_t *s); +/* The same screen as JSON: rows of text, style runs, cursor, hit-list. */ +char *screen_dump_json(screen_t *s); /* ---- pty --------------------------------------------------------------- */ |
