help: default the contextual layer off, and carry the help into the chooser
The contextual help was on by default, so a first run met a window with a "?" beside every surface it had not asked to have explained; `contextual_help` now defaults to false and the layer is asked for from the Help menu, from the chooser's new help menu, or with Ctrl+H. The source chooser runs before `App` exists, which makes it the window a user who does not know how to start is looking at, so it now carries the same three help affordances the window's Help view does: Documentation (the manual is another process and needs nothing of the app), Enable contextual help (a row whose check *is* the setting, written to the file the app reads a moment later), and Guided tour. The tour is drawn on the app's own window, so the chooser can only record the wish: it sets `Config::tour_pending` -- the value `main()` owns and hands to both `choose_source()` and `run_ui()` -- and `on_activate()` starts it once the window is up and laid out, through its own callback so the readings can tell a request from the first-run auto-start. The rows are the window's own `menu_button()`/`menu_toggle()`; `install_css()` therefore runs from `choose_source()` (it is idempotent now) so the popover gets the `.udpscope-menu` rules before it is shown. Opening the manual could also fail with a message that blamed the handler whatever was missing. `help_installed_path()` now resolves `help:<id>` the way the specification does and the failure alert says which of the two it is: with the set installed it names the viewer, without it it names the identifier, the expected installed path and the install command. `show_help()` gained an optional reporter, which `UDPSCOPE_PROBE_HELP_MS` uses for a new reading -- `[help] launch attempted= done= ok= error='' installed=` -- since a successful launch leaves no window of ours to observe. Tested: clean --clean-first build, three warnings as documented; test-ui 13/13 and test-help pass; no Gtk-CRITICAL in the help, helpui and chooser runs.
This commit is contained in:
1 parent
e140642ed0
commit
d8a79b96ba
15 files changed
+461
-66
No files matched your search
@@ -127,7 +127,10 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
|
||||
honest without knowing which dialog it is. One `GtkWidget*` (or `AdwDialog*`) per window, nulled
|
||||
in its own close handler, is the shape that prevents the double-open defect. `close_help_windows()`
|
||||
(misnamed now) closes just the two dialogs; a failed *launch* is reported by the launcher's own
|
||||
callback with a `GtkAlertDialog`, so a click that cannot open the manual says so.
|
||||
callback with a `GtkAlertDialog`, so a click that cannot open the manual says so. That callback is
|
||||
also `show_help()`'s **optional reporter** (`std::function<void(bool ok, const std::string& error)>`)
|
||||
— the one hook that runs on the success path, where no window of ours is left to observe; the probe
|
||||
uses it and nothing else does.
|
||||
- **`build_info.cpp` is generated, never committed.** `cmake/write_build_info.cmake` runs at
|
||||
configure time (so `add_executable` can name the file) and again on every build through
|
||||
`udpscope_build_info` (so the commit and the timestamp belong to the binary that is running).
|
||||
@@ -149,7 +152,21 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
|
||||
→ `org.udpscope.app`), so it is the `.desktop` name, the GApplication id and the install
|
||||
directory at once; `UDPSCOPE_HELP_NAME` and `UDPSCOPE_HELP_DIR` are compiled in from that one
|
||||
place. `show_help()` opens `help:<id>` with `GtkUriLauncher` (Yelp runs in its own process, so
|
||||
nothing here holds a pointer to it), and its failure callback shows a `GtkAlertDialog`.
|
||||
nothing here holds a pointer to it), and its failure callback shows a `GtkAlertDialog`. That
|
||||
failure is **careful about which thing is missing**: `gtk_uri_launcher_launch_finish()` reports a
|
||||
launch that could not be handed over — the *handler's* absence — and cannot tell that from a
|
||||
document that was never installed, so `help_installed_path()` walks the specification's own
|
||||
`$XDG_DATA_HOME/help/<lang>/<id>/` then `$XDG_DATA_DIRS/help/<lang>/<id>/` for an `index.page` and
|
||||
the dialog says which one it is: with the manual there, install a viewer (for example `yelp`); with
|
||||
it absent, the identifier, the expected installed path and the install command
|
||||
(`cmake --install build --prefix ~/.local`, which writes `~/.local/share/help/C/<id>/`) — and a
|
||||
viewer as well, the second possibility the error alone cannot rule out. Reporting a missing
|
||||
*document* as a missing *handler* is the defect that shape avoids.
|
||||
|
||||
`UDPSCOPE_PROBE_HELP_MS` launches it too, and its `[help] launch attempted= done= ok= error=''
|
||||
installed=` line is the reading — `ok=1` is the URI handed to a viewer and not a window on screen,
|
||||
since Yelp is another process and cannot map one headlessly; `installed=` sits beside it because a
|
||||
failing `ok=0` has to be read against whether the document was there at all.
|
||||
|
||||
`UDPSCOPE_PROBE_HELP_MS` no longer parses pages — they are files, not markup in a resource — so
|
||||
its `[help]` line asserts the set is *there*: `topics` (the `.page` files other than
|
||||
@@ -163,6 +180,25 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
|
||||
(GTK4 must be forced to the Cairo renderer, `GSK_RENDERER=cairo`, or the X11 surface reads back
|
||||
blank). Mallard is translatable with `itstool`, but there is no i18n set-up here: only the `C`
|
||||
set is authored.
|
||||
- **The chooser carries the same help affordances as the window, and the tour request crosses as a
|
||||
value — not a global.** The source chooser runs *before* `App` exists, so a user who has not started
|
||||
yet is the one least able to find the help; its header bar therefore has a help `GtkMenuButton`
|
||||
(the `.ui` holds the button, code holds the rows) whose three entries are the window's Help view's
|
||||
the same way — `ui_impl::menu_button()`/`menu_toggle()`, the app's own row shape — with the
|
||||
`.udpscope-menu` class on the popover. That class's rules only exist once `install_css()` has run, so
|
||||
`choose_source()` calls it before building the rows (`install_css()` is idempotent precisely because
|
||||
it now has two callers; the app's `on_activate()` still calls it and is a no-op by then). The rows
|
||||
show **no accelerators**: the window's Help view prints `F1`/`Ctrl+T` because the window binds them,
|
||||
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
|
||||
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.
|
||||
- **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
|
||||
|
||||
Reference in new issue
Block a user