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:
1 parent
395c9caec3
commit
829176248a
14 files changed
+911
-303
No files matched your search
@@ -193,13 +193,16 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
|
||||
and this dialog binds none, so a key printed here would be documentation that does nothing.
|
||||
*Documentation* calls `show_help()` straight from the chooser (the manual is another process and
|
||||
needs nothing of the app); *Enable contextual help* writes the settings file, which is what the app
|
||||
reads when it starts a moment later; *Guided tour* cannot start anything — the tour is drawn on the
|
||||
app's own window — so it sets **`Config::tour_pending`**, the one value `main()` owns and hands to
|
||||
reads when it starts a moment later, and **re-syncs this dialog's own "(i)" rows** through
|
||||
`chooser_help_sync()`; *Guided tour* starts a tour **of this window** -- the chooser's own walk --
|
||||
and that walk's last stop sets **`Config::tour_pending`**, the one value `main()` owns and hands to
|
||||
both `choose_source()` and `run_ui()` (`open_waveform` and the preferences' relative time cross the
|
||||
same way). `on_activate()` schedules `tour_start_requested()` 1.5 s later, the same delay the
|
||||
first-run auto-start uses, and **that callback is separate from `tour_autostart()` on purpose**: it
|
||||
sets `tour_requested`, not `tour_auto_started`, so `help layer:` says which of the two started the
|
||||
tour instead of conflating a user's request with a first run.
|
||||
window's half instead of conflating a user's request with a first run. The chooser's half has its own
|
||||
entry points in `source_dialog.cpp` (`chooser_tour_begin`, `chooser_tour_autostart`), and *that* walk
|
||||
is what a first run meets first -- see the tour bullets in the help-affordance section below.
|
||||
- **A `GtkPaned` hands its start child at least its minimum unless the position says otherwise.**
|
||||
Putting the events pane in a paned is what makes its width the user's to drag -- but with the
|
||||
position left alone, `shrink-start-child` or not, the pane's minimum is reserved as an empty column
|
||||
@@ -537,27 +540,69 @@ The `Help` submenu, the contextual help's "?" and the guided tour, and the traps
|
||||
stack, the visible child is the view, and `gtk_popover_present()` re-measures a popover that is
|
||||
already up. `UDPSCOPE_PROBE_MENUS_MS` walks the *visible page*, which is the one line the stack cost
|
||||
the probe.
|
||||
- **A "?" joins its surface's heading row as a sibling, not as an overlay child.** An overlay child
|
||||
sits *on* whatever is under it -- and every panel heading already has a switch or an [edit] button in
|
||||
a corner. `src/ui_context_help.cpp` is a table of (id, title, body, shortcut, host) where the host is
|
||||
the *heading box*, so a new surface is a row and nothing else. The one exception is the plot, which
|
||||
has no heading: its "?" is an overlay child of the overlay the layout editor already uses, and its
|
||||
corner is free. The icon is `dialog-question-symbolic` -- `help-about-symbolic` is *already* the
|
||||
status bar's information button, and two "help" glyphs meaning different things on the same line is
|
||||
the trap the seven app icons exist to avoid; the dump reads the name back through the theme for the
|
||||
same reason the pane [edit] buttons do.
|
||||
- **A "(i)" joins its surface's row as a sibling, not as an overlay child.** An overlay child
|
||||
sits *on* whatever is under it -- and every panel heading already has a switch or a pencil in a
|
||||
corner. `src/ui_context_help.cpp` is a table of (id, title, body, shortcut, host) where the host is
|
||||
the *row* -- a panel's heading usually, and the row of a specific control (the "record events"
|
||||
switch, the pre-trigger share) where that is the thing being explained. The one exception is the
|
||||
plot, which has no heading: its "(i)" is an overlay child of the overlay the layout editor already
|
||||
uses, and its corner is free. The icon is **`dialog-information-symbolic`** -- `help-about-symbolic`
|
||||
is *already* the status bar's information button, and two "help" glyphs meaning different things on
|
||||
the same line is the trap the seven app icons exist to avoid; the dump reads the name back through
|
||||
the theme for the same reason the pane [edit] buttons do. `math_head` exists only while the math
|
||||
editor is open, so that row is skipped when it is null.
|
||||
- **A `GtkMenuButton` ignores both `min-width` and a size request; its subnodes are where a small
|
||||
one is made.** The "(i)" is meant to be a *mark*, not a button, and the default is 34x34 (a 24 px
|
||||
floor plus 5 px of padding from Adwaita's `button` rule). Measured on libadwaita 1.10: setting
|
||||
`min-width`/`min-height` on the widget changed nothing, and neither did `gtk_widget_set_size_request()`
|
||||
-- the menu button's own measure wins. Three selectors are needed, all in `install_css()`:
|
||||
`menubutton.udpscope-hint` (the outer node), `menubutton.udpscope-hint > button` (its subnode) and
|
||||
`... > button > image` (the glyph), with `min-width: 0; min-height: 0; padding: 0` -- and the result
|
||||
is **16x16**, the glyph's own size, because a `min-width` is a floor and not a cap. (A class on the
|
||||
outer node alone leaves the subnode at 34; a class on the subnode alone shrank the width to 16 and
|
||||
left the height at 26.) The dump's `hint=` reading is that number, and it is measured with
|
||||
`gtk_widget_compute_bounds()` on the first *visible* hint -- a hint inside a collapsed `GtkExpander`
|
||||
is not in the widget-parent chain at all and reads 0x0, which would look like a mark shrunk to
|
||||
nothing.
|
||||
- **Off is gone, not greyed, and the buttons are found by a data key rather than kept in a list.** The
|
||||
list is what the math editor cannot survive: its heading lives in a builder that is dropped and
|
||||
rebuilt on every opening, so a stored pointer into it would go stale one dialog later. A key on the
|
||||
button (`udpscope-help-hint`, carrying the surface's id) is both the mark that says "this is a hint"
|
||||
and the name the probe and the dump report it by, and removing a hint is `gtk_widget_unparent()`,
|
||||
which means the same thing for a box and for the plot's overlay.
|
||||
which means the same thing for a box and for the plot's overlay. The button itself is
|
||||
`ui_impl::hint_button()` reached either by the table's `context_help_sync()` or by
|
||||
`context_help_button()` for a window with no `App` (the source chooser) -- one button, two callers,
|
||||
so the two windows cannot drift into two affordances.
|
||||
- **The guided tour takes no grab, and that is the whole reason it is an overlay.** Four dim
|
||||
rectangles around the hole are ordinary widgets that swallow the clicks that land on them and
|
||||
nothing else; `Skip`, `Finish` and `Escape` hide them, and there is no popover, no gesture and no
|
||||
grab to leak. The probe asserts it as a reading -- `controllers=` against the count taken before the
|
||||
tour opened -- rather than as a claim, because "no lingering grab" is exactly the sort of thing a
|
||||
later change can add back without noticing.
|
||||
- **The tour is one implementation over two windows.** `ui_impl::TourView` holds the overlay children
|
||||
and the walk's place in it (`tour_build`/`tour_begin`/`tour_advance`/`tour_end`/`tour_update`), and
|
||||
what differs between the windows is only the *stops*: a `TourStop` names a widget the owner resolves,
|
||||
so each window keeps its own table -- the main window's against `App` fields,
|
||||
`source_dialog.cpp`'s `kChooserStops` against the `Chooser`'s. A walk that passes its last stop calls
|
||||
the view's `on_done`; the window's passes null, the chooser's sets `Config::tour_pending`, which is
|
||||
how the two halves are one tour. `App` carries its own `TourView` (`app.tour`), so the machinery is
|
||||
compiled once and the probe reads either window's state by the same fields.
|
||||
- **The chooser's tour needs an overlay over its *whole* window, and `AdwWindow`'s content is
|
||||
replaced, not wrapped.** Two of the chooser's stops name header-bar buttons, and an overlay inside
|
||||
the `AdwToolbarView`'s `content` would give them negative coordinates and clamp the hole to the top
|
||||
edge. So the overlay *becomes* the window's content and adopts the toolbar view -- and the order
|
||||
matters: `gtk_overlay_set_child()` refuses a child that still has a parent, so
|
||||
`adw_window_set_content(win, overlay)` goes **first** (that call is what unparents the toolbar view)
|
||||
and `gtk_overlay_set_child(overlay, content)` second. The builder's object list still owns the view,
|
||||
so nothing is finalized in between. Getting the order wrong is a `Gtk-CRITICAL` and an empty
|
||||
chooser, which is exactly what the first version of this did.
|
||||
- **The chooser's hints are its own table because it runs before `App`.** An `AdwEntryRow` is not a
|
||||
box and its editor is internal, so a hint cannot join the host/port fields as a sibling -- appending
|
||||
it to the `AdwPreferencesGroup` would make it a row under the field rather than a mark beside it, so
|
||||
no hint is invented for them and the group's own `description` carries that text. The two rows the
|
||||
dialog *does* have -- the heading above the saved-source list and the waveforms page's action row --
|
||||
carry `chooser_sources` and `chooser_waveform`, added with the same `context_help_button()` the
|
||||
window uses and re-synced by its Help menu's toggle.
|
||||
- **The hole is kept from the last frame that could measure the target.** `gtk_widget_compute_bounds()`
|
||||
answers nothing on a frame that lands between two layout passes, and letting the hole empty there
|
||||
made the spotlight and the card jump to the corner and back; a *target that is not visible* is the
|
||||
@@ -567,8 +612,11 @@ The `Help` submenu, the contextual help's "?" and the guided tour, and the traps
|
||||
- **The first-run tour is a `settings.toml` key (`tour_seen`), written when the tour *starts*.** Not
|
||||
"the settings file did not exist": a user who has already changed the theme has a file and has still
|
||||
never seen the tour. Written on the way *in*, because a user who skips it in the first second has
|
||||
still seen it. The auto-start is a 1.5 s timer from `on_activate()`, so the window is up and laid out
|
||||
before anything points at it.
|
||||
still seen it. It starts **in the source chooser** when one is shown (the chooser is the surface a
|
||||
first run meets first, and the window's own auto-start is unreachable until the chooser has returned
|
||||
with a source) and in the window otherwise; either way it is a 1.5 s timer, so the window is up and
|
||||
laid out before anything points at it. The chooser's walk writes the key itself and hands the second
|
||||
half over by `Config::tour_pending`, so a first run is *one* tour that crosses the two windows.
|
||||
- **The `help figures:` line is captured on the tick, like every other size the dump prints.** It names
|
||||
ten surfaces' window-coordinate rectangles for the help's annotated figures, and the dump runs after
|
||||
the window is destroyed -- a `gtk_widget_compute_bounds()` there is the "no `gtk_widget_*` call in the
|
||||
|
||||
@@ -395,21 +395,32 @@ Two lines of the self-check output are assertions in disguise:
|
||||
on the first tick for the same reason the toolbar's are. **Both must read `(ok)`**: the page titles are
|
||||
empty on purpose, so an icon that does not resolve leaves a *blank* pill, and a blank pill looks
|
||||
exactly like a page with nothing in it.
|
||||
- `help layer: contextual=on hints=8 ids={events plot status cursors measures trigger signals window} icon=dialog-question-symbolic(ok); tour=idle steps=5 step=0 auto=1 requested=0` (in the exit
|
||||
- `help layer: contextual=on hints=11 ids={events plot status cursors measures trigger trigger_advanced events_record signals signals_config window} icon=dialog-information-symbolic(ok) hint=16x16; tour=idle steps=5 step=0 auto=1 requested=0` (in the exit
|
||||
dump, beside `switcher:`) — the help affordance layer as the last tick found it. **`hints=` must equal
|
||||
the number of ids**, and the ids are the surfaces the contextual help is on: the eight of the window
|
||||
the number of ids**, and the ids are the surfaces the contextual help is on: ten of the window
|
||||
itself, and `math` only while the math editor is open (its heading lives in a builder that is rebuilt
|
||||
on every opening, so it is not one of the window's own). The layer is **off by default**
|
||||
on every opening, so it is not one of the window's own). Three of the ten are not a pane's *heading*
|
||||
but the row of a specific control — `events_record` (the "record events" switch in the trigger
|
||||
panel), `trigger_advanced` (the pre-trigger share row) and `signals_config` (the signals pane's hint
|
||||
line, whose box exists so a hint can join it) — which is the rule the layer follows: a hint is a
|
||||
sibling of the thing it explains and never an overlay on it. The layer is **off by default**
|
||||
(`contextual_help` in `settings.toml` is false for a missing file), so a fresh-config run reads
|
||||
`contextual=off hints=0` and that line above is the state *after* the Help row was switched on;
|
||||
`contextual=off` beside a non-zero count is the toggle not having removed its buttons — **off is
|
||||
*gone*, not greyed**. **`icon=` must read `(ok)`**: a `?"` whose name Adwaita lacks is a
|
||||
*blank* control that still works, the failure the pane [edit] buttons already paid for once. `tour=`
|
||||
is `running`/`idle` with the plan's `steps=` and the current `step=`; `auto=1` is the first-run
|
||||
auto-start having fired *in this process* — the flag is `tour_seen` in `settings.toml`, so a second run
|
||||
against the same config directory reads `auto=0` — and `requested=1` is the **chooser's** "Guided tour"
|
||||
(`Config::tour_pending`) having been carried into this run instead, which is `auto=0` because it is not
|
||||
the auto-start.
|
||||
*gone*, not greyed**. **`icon=` must read `(ok)`**: an "(i)" whose name Adwaita lacks is a
|
||||
*blank* control that still works, the failure the pane [edit] buttons already paid for once. The name
|
||||
is `dialog-information-symbolic`, the plain information mark; `help-about-symbolic` is the status
|
||||
bar's ⓘ and a second meaning for it is what the app's own icons exist to avoid. `hint=WxH` is the
|
||||
size the **first visible** hint was allocated, measured the way every other rectangle here is
|
||||
(`gtk_widget_compute_bounds()`), and **16x16 is the reading a "much tinier" mark must keep**: the
|
||||
class zeroes the outer `menubutton` node, its `button` subnode and the glyph, which is what a
|
||||
`GtkMenuButton` needs (its measure ignores both `min-width` on the widget and a size request) — the
|
||||
default 34x34 is the number to compare against. Hints inside a collapsed expander are skipped, so the
|
||||
number is never a hidden widget's 0x0. `tour=` is `running`/`idle` with the plan's `steps=` and the
|
||||
current `step=`; `auto=1` is the first-run auto-start having fired *in this process* — the flag is
|
||||
`tour_seen` in `settings.toml`, so a second run against the same config directory reads `auto=0` —
|
||||
and `requested=1` is the **chooser's** tour having handed over (`Config::tour_pending`), which is
|
||||
`auto=0` because the request came from the other window rather than from this process's first run.
|
||||
- `gtk warnings: N` (in the exit dump, beside `help layer:`) — **GTK's own log at warning or above,
|
||||
counted for the whole run, and it must read `0`.** It is counted through a log *writer* function
|
||||
because GTK is built with structured logging: its messages go through the writer and never through
|
||||
@@ -472,6 +483,50 @@ Two lines of the self-check output are assertions in disguise:
|
||||
connect_sensitive=1` then a `picked` line, with no SIGSEGV, which is as much a crash test of a
|
||||
dialog built and destroyed as it is a state check. An empty list must print `picked nothing:
|
||||
the list is empty` rather than dereferencing a null row.
|
||||
|
||||
**The command that reaches the chooser at all is `UDPSCOPE_PROBE_PICK_MS`, and this is worth
|
||||
saying because three earlier attempts found no chooser and no output:** with no `--server` and no
|
||||
probe, the chooser runs its own nested `GMainLoop` and *blocks* — there is nothing to time it out
|
||||
and no dump runs, so a bare `./build/udpscope` (bare or under a pty) sits there silently. The
|
||||
working form, against the mock:
|
||||
|
||||
```sh
|
||||
xvfb-run -a env UDPSCOPE_EXIT_AFTER_MS=6000 UDPSCOPE_PROBE_PICK_MS=900 \
|
||||
./build/udpscope
|
||||
```
|
||||
|
||||
(with `XDG_CONFIG_HOME` pointing at a directory holding at least one saved source, or the pick
|
||||
finds an empty list and the run prints `picked nothing`). It is the same command the docs give
|
||||
elsewhere with `--server` removed and `UDPSCOPE_PROBE_PICK_MS` added.
|
||||
- `[sources] chooser ui: … hints=[N {ids}] hint=WxH` (stderr, `UDPSCOPE_PROBE_PICK_MS`) — the
|
||||
chooser's frame *and* its help layer in one line. `hints=[2 {chooser_sources chooser_waveform}]`
|
||||
is the layer **on** (`contextual_help` in the file the run reads) and `hints=[0 {}] hint=0x0` is
|
||||
it **off**, which is the same "off is gone" rule the window's line reads, in the window that runs
|
||||
before `App` exists. The two ids are the surfaces this dialog has a row for — the heading above
|
||||
the saved-source list and the waveforms page's action row; the form's `AdwEntryRow`s are *not*
|
||||
hosts (a row is not a box and its editor is internal, so a hint cannot join it as a sibling) and
|
||||
the connection fields are explained by their group's `description` instead. `hint=WxH` is the
|
||||
same 16x16 the window's line reads: the button is `ui_impl::context_help_button()`, the one
|
||||
`udpscope-hint` affordance both windows draw.
|
||||
- `[sources] tour: first run -- auto_started=1 in the chooser` then
|
||||
`[sources] chooser tour: visible=1 steps=5 step=0` (stderr) — **a first run's tour starts in the
|
||||
chooser**, on the chooser's own widgets, from the same `settings.tour_seen` the window's
|
||||
auto-start reads and with the same 1.5 s delay. `steps=5` is the chooser's plan (the source list,
|
||||
the two tabs, New host, the help menu and the preferences). Driven by the walk itself:
|
||||
|
||||
- `UDPSCOPE_PROBE_CHOOSER_TOUR=1` emits `::clicked` on the help menu's **Guided tour** row, which
|
||||
now starts *this* walk rather than only requesting the window's: `[sources] chooser help: tour
|
||||
started in the chooser`, then `[sources] chooser tour: visible=1 steps=5 step=0`, then a walking
|
||||
`[sources] chooser tour: next -> step=N/5` per press, then `[sources] chooser tour: finished 5
|
||||
stops -- the window continues it (tour_pending=1)`. **`tour_pending=1` and `visible=0` is the
|
||||
handoff assertion** — the walk is over here and the request rides on the one `Config` value
|
||||
`main()` hands to both windows.
|
||||
- `UDPSCOPE_PROBE_CHOOSER_TOUR_MS=<ms>` schedules the same walk on a timer, for reading a tour
|
||||
**the run itself started** (the first-run auto-start) rather than one the probe started; it must
|
||||
be later than 1500 ms. Paired with `UDPSCOPE_PROBE_PICK_MS` a few hundred ms later, the run then
|
||||
shows the other half: the application's `help layer:` reads `tour=running … auto=0 requested=1`,
|
||||
the window's tour having been started by `tour_start_requested()` rather than by the first-run
|
||||
timer.
|
||||
- **The session layout round trip** (`~/.config/udpscope/<host>_<port>.toml`) — run once
|
||||
with a drop and a window change, then again with no interaction: the second run's dump
|
||||
must read `layout loaded from ...` and `layout: rows=R window_s=W row0=[...]` with the
|
||||
@@ -685,12 +740,16 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
|
||||
touches anything: `auto_started=1 visible=1` is the tour that started itself, and the parenthetical is
|
||||
`settings.tour_seen` as the process found it — `tour_seen already set` with `auto=0` is the *second*
|
||||
run against the same config directory, which is the assertion that the flag persisted. Then:
|
||||
- `[helpui] contextual on: hints=8 ids={events plot status cursors measures trigger signals window}` —
|
||||
the eight "?" affordances, by id. The layer's ninth surface, `math`, is not here: its host exists
|
||||
only while the math editor window is open. **On a fresh config this reads `hints=0 ids={}`**, because
|
||||
the layer is off by default; the example is the state after the row below was switched on, and a
|
||||
fresh run's `hints=0` beside a `settings.toml` with no `contextual_help` key is the default being
|
||||
read rather than assumed.
|
||||
- `[helpui] contextual on: hints=11 ids={events plot status cursors measures trigger trigger_advanced events_record signals signals_config window} hint=16x16` —
|
||||
the eleven "(i)" affordances, by id, and the size the first visible one was allocated. Ten are the
|
||||
window's own surfaces (three of them a specific control's row rather than a heading — see the
|
||||
`help layer:` entry) and the eleventh is `math`, which is present only while the math editor
|
||||
window is open; it reads 10 with the editor shut. **On a fresh config this reads `hints=0 ids={}`
|
||||
and `hint=0x0`**, because the layer is off by default; the example is the state after the row below
|
||||
was switched on, and a fresh run's `hints=0` beside a `settings.toml` with no `contextual_help`
|
||||
key is the default being read rather than assumed. **`hint=16x16` is the "much tinier" assertion**
|
||||
— the default menu-button mark is 34x34 (see `help layer:`), and anything near that is the class
|
||||
not reaching the outer `menubutton` node.
|
||||
- `[helpui] main view: rows=7 help_row=1` and one `[helpui] entry N '<label>' accel='<key>' order=O`
|
||||
per row of the **Help view** — `entry 0 'Back'` with no accelerator and then the four the submenu
|
||||
promises: `entry 1 'Keyboard shortcuts' accel='Ctrl+/'`, `entry 2 'Documentation' accel='F1'`,
|
||||
@@ -701,10 +760,10 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
|
||||
`toggle=` being the contextual-help row's check, which *is* `settings.contextual_help`. It reads `0`
|
||||
on a fresh config (the default) and `1` on one where the setting is on; the probe's next step drives
|
||||
it both ways, which is why the example here is the `1` side.
|
||||
- `[helpui] toggle: off -> hints=0 ids={}; on -> hints=8 ids={…}; setting=on` — the toggle's effect
|
||||
- `[helpui] toggle: off -> hints=0 ids={}; on -> hints=11 ids={…}; setting=on` — the toggle's effect
|
||||
read both ways through the row itself. **`hints=0` with `off` is the assertion**: off means the
|
||||
affordances are *gone*, not greyed, so anything else is a row that hid its buttons instead of
|
||||
removing them. The count comes back to the same eight, which is the other half — a toggle that
|
||||
removing them. The count comes back to the same eleven, which is the other half — a toggle that
|
||||
removed and could not restore is a one-way switch.
|
||||
- `[helpui] tour started from the probe: visible=1 steps=5 step=0` — the tour started the way
|
||||
`Ctrl+T` starts it. `steps=5` is the plan: the table's five steps whose target was on screen
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user