help: a tinier (i), hints beside their controls, and the tour starting in the chooser

The contextual help becomes the affordance the ask names: a plain (i)
(`dialog-information-symbolic`) at **16x16**, and one that sits beside the
control it explains rather than only in a pane's heading.

- The mark: `GtkMenuButton` ignores `min-width` on the widget and a size
  request, so the size is made in `install_css()` on all three nodes (outer
  `menubutton`, its `button` subnode, the glyph). Measured 16x16 against the
  default 34x34; the dump prints it as `hint=WxH`, measured with
  `gtk_widget_compute_bounds()` on the first *visible* hint.
- More sites: `events_record` (the "record events" switch in the trigger
  panel), `trigger_advanced` (the pre-trigger share row), `signals_config`
  (the signals pane's hint line, wrapped in a box so a hint can join it).
  Hints join as siblings, so none can cover a switch, pencil or dropdown.
- The source chooser gets its own layer -- `chooser_sources` (a new heading
  above the saved-source list) and `chooser_waveform` (the waveforms action
  row) -- built with the one `context_help_button()` both windows use and
  re-synced by its Help menu's toggle. The form's `AdwEntryRow`s cannot host a
  sibling hint, so none is invented for the host/port fields.
- The tour is one implementation over two windows: `ui_impl::TourView` plus a
  list of `TourStop`s; each window keeps its own table. A walk that passes its
  last stop calls `on_done`, and the chooser's sets `Config::tour_pending`, so
  a first run is one tour that crosses from the chooser into the app. The
  chooser's tour auto-starts from `settings.tour_seen` exactly as the window's
  does, and its "Guided tour" row now starts *it* instead of only requesting
  the window's.
- Probes: `UDPSCOPE_PROBE_CHOOSER_TOUR=1` / `UDPSCOPE_PROBE_CHOOSER_TOUR_MS`,
  the hint size in the `help layer:`/`[helpui] contextual on:` lines, and the
  chooser's hints in its `chooser ui:` line. Docs updated in
  invariants-gtk-and-chrome.md, probe-readings.md and verification.md.
This commit is contained in:
Martino Ferrari committed 2026-10-14 22:42:38 +02:00
1 parent 395c9caec3
commit 829176248a
14 files changed
+911 -303

No files matched your search

+18 -5
View File
@@ -309,16 +309,19 @@ as distinct from the fault injection below, which exercises ingest:
- `UDPSCOPE_PROBE_HELPUI_MS` — the help affordance layer, end to end, in ten steps 300–400 ms apart:
the **first-run auto-start** (run it once with a throwaway `XDG_CONFIG_HOME` to see `auto=1`, and
again against the same one to see it not repeat), the menu's seven rows and the **four entries of
the Help submenu**, the **contextual-help toggle** with the count of "?" affordances on either side
the Help submenu**, the **contextual-help toggle** with the count of "(i)" affordances on either side
of it, the tour **started from the probe** and stepped forwards, back and dismissed, and `help
figures:` read in both of the trigger pane's modes. Its lines and what each asserts are in
[probe-readings.md](probe-readings.md); the two things to read first are **`hints=0`** while the
toggle is off (off is *gone*, not greyed) and **`controllers=12 (was 12)`** after the dismissal (no
lingering input grab — a tour of ordinary overlay widgets takes none). Give it
lingering input grab — a tour of ordinary overlay widgets takes none), and **`hint=16x16`** is the
size the shrunk "(i)" must keep (the default menu-button mark is 34x34). The chooser's own tour is
the other half and has its own entry points — see the **chooser** bullet below. Give it
`UDPSCOPE_EXIT_AFTER_MS=9500 UDPSCOPE_EXIT_DUMP=1` to get the `help layer:`/`help figures:` dump
lines as well, and note the tour **auto-starts** in any run whose settings file does not carry
`tour_seen`, so a probe run against a fresh config directory will have it on screen for the first
second and a half — and that start *writes* `tour_seen` to whichever config directory the run is
`tour_seen` — **in the source chooser when there is one**, in the window otherwise (see the chooser
bullet) — so a probe run against a fresh config directory will have it on screen for the first
second and a half, and that start *writes* `tour_seen` to whichever config directory the run is
using, which is why the second run against the same one reads `auto=0`.
- `UDPSCOPE_PROBE_DEFAULTS_MS` — opens **Calibrate** and reads every spin button in it and in the
trigger panel: `[defaults] calibrate: 1 0 model=1 0 | trigger: 0.001 0.002 0 0.001 0 50 0.01`. A
@@ -331,7 +334,17 @@ as distinct from the fault injection below, which exercises ingest:
entry per configuration (`host:port/name … buffer= relative= note='…'`), and
`UDPSCOPE_PROBE_PICK_MS=800` opens the chooser, picks the first row and prints
`[sources] picked host:port … buffer=64 relative=0 capture=0 config=… note='…'` — the settings the
configuration carried, into the `Config` the model is built from. A legacy file
configuration carried, into the `Config` the model is built from. **With no `--server` and no probe
the chooser blocks in its own nested loop** (no frame to end and no dump), so a chooser run is
always this probe. It also prints the dialog's frame *and its own help layer*:
`[sources] chooser ui: … hints=[2 {chooser_sources chooser_waveform}] hint=16x16` with the setting
on, `hints=[0 {}] hint=0x0` with it off. `UDPSCOPE_PROBE_CHOOSER_HELP=1` drives the **Enable
contextual help** row and reads the file back; `UDPSCOPE_PROBE_CHOOSER_TOUR=1` drives the **Guided
tour** row and walks the chooser's own tour to its last stop, printing `[sources] chooser tour: …`
and the handoff (`tour_pending=1`); `UDPSCOPE_PROBE_CHOOSER_TOUR_MS=<ms>` schedules the same walk,
which is how the **first-run** auto-start is read (schedule it after 1500 ms, and pair it with
`UDPSCOPE_PROBE_PICK_MS` a little later so the application's half follows). Its lines and what each
asserts are in [probe-readings.md](probe-readings.md). A legacy file
(`<host>_<port>.toml`) produces `layout loaded from …/<host>_<port>/default.toml`, an `active`
holding `default`, and the old file renamed `.imported`.
- **The loading window covers the gap, and only on the path that asked.** The same