fix: the guided tour selects the page a stop's target lives on

A stop whose target is on another page of a stack was entered without
switching to that page, so the spotlight aimed at a widget that was not
on screen. A stop now declares the page it stands on (`TourStop::page`)
and the tour selects it as the step is entered -- the window's trigger
and signals stops put the sidebar on Signals, the chooser's tabs stop
shows the Waveforms page and stepping off it brings Sources back.

The stop filter moved into `tour_begin()` and now runs on
`gtk_widget_get_mapped()`: GTK 4.24's `is_visible()` ignores
`child_visible`, so it kept a stop on another page *and* one in a
collapsed pane alike. A wrong page is kept and selected; a collapsed
pane, whose stack is unmapped too, is still dropped.
This commit is contained in:
Martino Ferrari committed 2026-10-14 23:01:43 +02:00
1 parent 829176248a
commit d549223889
9 files changed
+385 -89

No files matched your search

+18 -10
View File
@@ -924,20 +924,28 @@ the window's own `menu_button()`/`menu_toggle()` -- the same shape, and the same
stylesheet, whose rules `choose_source()` installs before building them since the app installs them
later. *Documentation* opens the manual directly (it is another process and needs nothing of the app),
*Enable contextual help* writes the settings file the app reads a moment later, and *Guided tour*
cannot start anything -- the tour is drawn on the app's window, which does not exist yet -- so it sets
**`Config::tour_pending`**, the value `main()` owns and hands to both the chooser and the front end
(`open_waveform` crosses the same way). Half a second and a half after the window is up, the same
delay the first-run auto-start uses, the pending request starts the tour; it sets `tour_requested`
rather than `tour_auto_started`, so the readings say which of the two it was. The chooser's rows show
**no accelerators** -- the window prints `F1`/`Ctrl+T` because the window binds them, and this dialog
binds none.
starts **the chooser's own walk** -- the surfaces a first run meets first are this dialog's own --
whose last step sets **`Config::tour_pending`**, the value `main()` owns and hands to both the chooser
and the front end (`open_waveform` crosses the same way). Half a second and a half after the window is
up, the same delay the first-run auto-start uses, the pending request starts the window's tour; it sets
`tour_requested` rather than `tour_auto_started`, so the readings say which of the two it was. The
chooser's rows show **no accelerators** -- the window prints `F1`/`Ctrl+T` because the window binds
them, and this dialog binds none.
**The guided tour is five steps on a `GtkOverlay`** inserted above the window's content: the plot,
the side panel, the trigger, the signals and the status line. There is no popover anywhere in it and
therefore no pointer grab to lose: what makes the tour modal is four dim rectangles -- above, below
and either side of the target -- that swallow the clicks that land on them, and
`gtk_widget_is_visible()` decides which steps exist at all (a widget under a hidden parent keeps its
own flag true, so `get_visible()` would have walked over surfaces that are not there).
and either side of the target -- that swallow the clicks that land on them. A stop declares the
**page it stands on** (the trigger and the signals steps live on the sidebar's *Signals* page, named
in `TourStop::page`), and the tour selects that page as the step is entered -- on the frame *after*
the switch, since a stack allocates a new page's widgets a frame late -- so the spotlight lands on a
widget the user had left behind on the other tab instead of on nothing. `gtk_widget_get_mapped()`
decides which steps exist at all: a stop on the *wrong page* is kept, because selecting its page
reveals it, while one whose *pane is collapsed* is dropped, because the stack is unmapped with it
(a hidden page keeps its own *visible* flag true -- the widget's own flag, which is all
`is_visible()` walks -- so the old test walked over surfaces that were not on screen). The chooser's
tour works the same way over its own two pages: its tabs step shows the *Waveforms* page and
stepping off it -- in either direction -- brings the *Sources* page back.
Everything is placed from `gtk_widget_compute_bounds()`, re-read on **every frame**, because a
widget's allocation is 0 on the frame it is first shown and a window resize moves it under a