docs: fix five accuracy findings in the libadwaita and icon documentation
- CLAUDE.md: the libadwaita dependency paragraph now names both AdwDialog widgets (AdwShortcutsDialog and AdwAboutDialog), explains the shared on_dialog_closed() handler keyed by pointer-to-pointer, and covers both show_about() and show_shortcuts() in the AdwDialog sentence. - CLAUDE.md: the icon-authoring invariant's explanation of how Icon= in the desktop entry resolves now names the installed copies under $XDG_DATA_HOME/icons/hicolor/scalable/apps and .../symbolic/apps, not the GResource (a desktop shell cannot read a compiled-in resource). - CLAUDE.md: [help] probe example byte count corrected from 1381 to 1379 (measured: wc -c src/help/01-overview.txt = 1379). - README.md + udpscope.gresource.xml: "file, line and column" corrected to "file and line number (plus a caret under the offending character)" to match xmllint's actual output; also removes -- from the XML comment where it was illegal. - README.md: desktop-file-validate described as a hard failure "when the tool is on PATH", matching cmake/install_desktop_entry.cmake lines 44-54. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
e2be597698
commit
02c53bb7a0
3 files changed
+26
-17
No files matched your search
@@ -44,16 +44,21 @@ form for a new host. Every probe below passes `--server`, so none of them sees i
|
|||||||
vendored C99 source pair compiled into a static lib.
|
vendored C99 source pair compiled into a static lib.
|
||||||
|
|
||||||
**libadwaita ≥ 1.8 is a system dependency** (`pkg_check_modules(ADWAITA ... libadwaita-1>=1.8)`),
|
**libadwaita ≥ 1.8 is a system dependency** (`pkg_check_modules(ADWAITA ... libadwaita-1>=1.8)`),
|
||||||
for exactly one widget: the shortcut overview is an `AdwShortcutsDialog`. GTK4's own
|
for two widgets: the shortcut overview (`AdwShortcutsDialog`) and the About dialog
|
||||||
`GtkShortcutsWindow` is deprecated as of 4.18 and that is its replacement. Two consequences
|
(`AdwAboutDialog`). GTK4's own `GtkShortcutsWindow` is deprecated as of 4.18 and
|
||||||
worth knowing before editing. `adw_init()` is called — in `run_ui()` and, since the chooser
|
`AdwShortcutsDialog` is its replacement; `GtkAboutDialog` still exists but
|
||||||
runs first and must be styled the same, in `choose_source()` in place of its `gtk_init()`
|
`adw_about_window_new()` is deprecated in favour of `AdwAboutDialog`, which shows the
|
||||||
(both are idempotent) — so **the whole app is drawn with libadwaita's stylesheet**, not
|
application icon as the page's own header. Two consequences worth knowing before editing.
|
||||||
GTK's: a metric change there reaches every widget, and `layout over N frames` /
|
`adw_init()` is called — in `run_ui()` and, since the chooser runs first and must be styled
|
||||||
`axes.w changes` is what says whether the layout still settles. And an `AdwDialog` is
|
the same, in `choose_source()` in place of its `gtk_init()` (both are idempotent) — so
|
||||||
**not** a `GtkWindow`: `show_shortcuts()` keeps an `AdwDialog*`, clears it on `::closed`
|
**the whole app is drawn with libadwaita's stylesheet**, not GTK's: a metric change there
|
||||||
(there is no `::close-request`) and closes it with `adw_dialog_close()`. Presenting it on
|
reaches every widget, and `layout over N frames` / `axes.w changes` is what says whether
|
||||||
this app's plain `GtkApplicationWindow` is supported and warning-free; it was checked.
|
the layout still settles. And an `AdwDialog` is **not** a `GtkWindow`: both `show_about()`
|
||||||
|
and `show_shortcuts()` keep an `AdwDialog*`, cleared on `::closed` (there is no
|
||||||
|
`::close-request`) and closed with `adw_dialog_close()`. They share one `on_dialog_closed()`
|
||||||
|
handler keyed by a pointer-to-pointer (`gpointer slot` cast to `AdwDialog**`), so one
|
||||||
|
handler clears either pointer without knowing which dialog it is. Presenting either on this
|
||||||
|
app's plain `GtkApplicationWindow` is supported and warning-free; it was checked.
|
||||||
|
|
||||||
`deps/plotter` is upstream's own repository and this app's figure support was added
|
`deps/plotter` is upstream's own repository and this app's figure support was added
|
||||||
there rather than worked around here: `Figure::set_min_y_gutter()` (a floor under the
|
there rather than worked around here: `Figure::set_min_y_gutter()` (a floor under the
|
||||||
@@ -614,7 +619,7 @@ Two lines of the self-check output are assertions in disguise:
|
|||||||
so the panes the tick rewrites are measured directly. The `[width-probe]` lines are the
|
so the panes the tick rewrites are measured directly. The `[width-probe]` lines are the
|
||||||
per-change detail behind the `axes.w changes` count, and a step over 100 px dumps the widget
|
per-change detail behind the `axes.w changes` count, and a step over 100 px dumps the widget
|
||||||
tree's wide subtrees — that is what the documented, intermittent ~320 px step wants read.
|
tree's wide subtrees — that is what the documented, intermittent ~320 px step wants read.
|
||||||
- `[help] pages=14 parsed=14 shortest='Overview' 1381 B; shortcuts: app=12 plot=13; about version=… commit=… built=… settings=… icon=org.udpscope.app; closed ok` (stderr, `UDPSCOPE_PROBE_HELP_MS`) — **`parsed` must equal `pages`** and no page may be empty: a missing resource or markup Pango rejects renders a one-line stand-in instead of failing, so the window *looks* fine and only this count notices. `settings=` must be a real path (the same one the About dialog shows). **`icon=` must read `org.udpscope.app`** — it is read back through `adw_about_dialog_get_application_icon()` while the dialog is open, so the dialog is asserted to *carry* the icon rather than merely to open (a `set_application_icon()` lost in an edit leaves a dialog that opens, looks almost right, and shows a generic placeholder). `closed ok` with **no `Gtk-CRITICAL`** is as much a crash test of three windows built, presented and closed in one run as it is a state check, and a stronger one than it was: the three are now closed by **two different calls**, so a mismatched pair crashes or leaks here. One of the three is a `GtkWindow` (the help window, `gtk_window_close()`); the About dialog and the shortcut overview are `AdwDialog`s and close with `adw_dialog_close()`, cleared on `::closed`. `shortest=` is the page title — a page whose body was never compiled into the binary is absent rather than empty, and a title alone is the stand-in's shape.
|
- `[help] pages=14 parsed=14 shortest='Overview' 1379 B; shortcuts: app=12 plot=13; about version=… commit=… built=… settings=… icon=org.udpscope.app; closed ok` (stderr, `UDPSCOPE_PROBE_HELP_MS`) — **`parsed` must equal `pages`** and no page may be empty: a missing resource or markup Pango rejects renders a one-line stand-in instead of failing, so the window *looks* fine and only this count notices. `settings=` must be a real path (the same one the About dialog shows). **`icon=` must read `org.udpscope.app`** — it is read back through `adw_about_dialog_get_application_icon()` while the dialog is open, so the dialog is asserted to *carry* the icon rather than merely to open (a `set_application_icon()` lost in an edit leaves a dialog that opens, looks almost right, and shows a generic placeholder). `closed ok` with **no `Gtk-CRITICAL`** is as much a crash test of three windows built, presented and closed in one run as it is a state check, and a stronger one than it was: the three are now closed by **two different calls**, so a mismatched pair crashes or leaks here. One of the three is a `GtkWindow` (the help window, `gtk_window_close()`); the About dialog and the shortcut overview are `AdwDialog`s and close with `adw_dialog_close()`, cleared on `::closed`. `shortest=` is the page title — a page whose body was never compiled into the binary is absent rather than empty, and a title alone is the stand-in's shape.
|
||||||
- `[keys] a: armed 0->1 | space: paused 0->1 | t: trigger panel: 0->1 | … | editable focused: 'm' refused=1` (stderr, `UDPSCOPE_PROBE_KEYS_MS`) — **every `X->Y` pair must differ** and **`refused` must be 1**. The refusal is the whole reason the controller is in the bubble phase: every bare-letter accel is also a character, so an accel that fires while a `GtkEditable` has focus makes the window entry unusable. A pair reading `0->0` is an action whose dispatch does not reach the handler a click reaches. Note the format is `<key>: <widget-description>: <before>-><after>` — the name passed to `before_after()` includes the widget's description, so `t: trigger panel: 0->1` is the correct form (not `t: trigger panel 0->1` without the colon before the values).
|
- `[keys] a: armed 0->1 | space: paused 0->1 | t: trigger panel: 0->1 | … | editable focused: 'm' refused=1` (stderr, `UDPSCOPE_PROBE_KEYS_MS`) — **every `X->Y` pair must differ** and **`refused` must be 1**. The refusal is the whole reason the controller is in the bubble phase: every bare-letter accel is also a character, so an accel that fires while a `GtkEditable` has focus makes the window entry unusable. A pair reading `0->0` is an action whose dispatch does not reach the handler a click reaches. Note the format is `<key>: <widget-description>: <before>-><after>` — the name passed to `before_after()` includes the widget's description, so `t: trigger panel: 0->1` is the correct form (not `t: trigger panel 0->1` without the colon before the values).
|
||||||
- `[zoomkeys] ctrl+plus x=[..]->[..] y_held=1 | alt+plus y=[..]->[..] x_held=1` (stderr, `UDPSCOPE_PROBE_ZOOMKEYS_MS`) — **both `_held` must be 1 and both zooms must still happen.** Run it inside a pinned state, where a frame cannot re-frame the other axis for its own reasons: `UDPSCOPE_PROBE_PAUSE_MS=1500 UDPSCOPE_PROBE_ZOOMKEYS_MS=2200`. A `_held=0` is the modifier not reaching the plotter's controller; an unchanged range on the *zoomed* axis is the opposite failure, the key doing nothing. Ctrl restricts to x and Alt to y; Ctrl+Alt zooms neither (no special case needed — neither flag alone fires).
|
- `[zoomkeys] ctrl+plus x=[..]->[..] y_held=1 | alt+plus y=[..]->[..] x_held=1` (stderr, `UDPSCOPE_PROBE_ZOOMKEYS_MS`) — **both `_held` must be 1 and both zooms must still happen.** Run it inside a pinned state, where a frame cannot re-frame the other axis for its own reasons: `UDPSCOPE_PROBE_PAUSE_MS=1500 UDPSCOPE_PROBE_ZOOMKEYS_MS=2200`. A `_held=0` is the modifier not reaching the plotter's controller; an unchanged range on the *zoomed* axis is the opposite failure, the key doing nothing. Ctrl restricts to x and Alt to y; Ctrl+Alt zooms neither (no special case needed — neither flag alone fires).
|
||||||
- `status bar: glance=[● live · 1.09 MS/s · 2 s window] max_glance_chars=53 detail_fields=11 popover_rebuilds=0` (exit dump) — **`max_glance_chars` must stay small** (under about 60) and **`popover_rebuilds` must be 0**. The status row is directly above the plot, so this is the "layout must not depend on content" rule read from the bar's own side: the state field is one word from a fixed set, the rate field is `%.3g` (so `10 kS/s`, never `10.0 kS/s`), and the only field trigger mode adds is the elapsed time, which steps units rather than growing digits. `detail_fields` is the popover's label count, a literal, so adding a label without thinking about layout shows up here. The glance rate format matters: `%.3g` drops the trailing zero that a `%.4g` or a fixed-precision format would keep — a rate that reads differently in the dump and in the help page is a format disagreement, and `14-status.txt`'s example must match it.
|
- `status bar: glance=[● live · 1.09 MS/s · 2 s window] max_glance_chars=53 detail_fields=11 popover_rebuilds=0` (exit dump) — **`max_glance_chars` must stay small** (under about 60) and **`popover_rebuilds` must be 0**. The status row is directly above the plot, so this is the "layout must not depend on content" rule read from the bar's own side: the state field is one word from a fixed set, the rate field is `%.3g` (so `10 kS/s`, never `10.0 kS/s`), and the only field trigger mode adds is the elapsed time, which steps units rather than growing digits. `detail_fields` is the popover's label count, a literal, so adding a label without thinking about layout shows up here. The glance rate format matters: `%.3g` drops the trailing zero that a `%.4g` or a fixed-precision format would keep — a rate that reads differently in the dump and in the help page is a format disagreement, and `14-status.txt`'s example must match it.
|
||||||
@@ -1304,8 +1309,12 @@ far the largest file.
|
|||||||
measurements and math. `src/icons/scalable/actions/udpscope-{trigger,cursors,measure,math}-symbolic.svg`
|
measurements and math. `src/icons/scalable/actions/udpscope-{trigger,cursors,measure,math}-symbolic.svg`
|
||||||
are the four action icons; beside them in `src/icons/scalable/apps/` are the two
|
are the four action icons; beside them in `src/icons/scalable/apps/` are the two
|
||||||
**application** icons, `org.udpscope.app.svg` (128px colour artwork) and
|
**application** icons, `org.udpscope.app.svg` (128px colour artwork) and
|
||||||
`org.udpscope.app-symbolic.svg` (16px), whose `apps` context is where an icon theme keeps an
|
`org.udpscope.app-symbolic.svg` (16px). The `apps` context is where an icon theme keeps an
|
||||||
application's own icon and is what makes `Icon=org.udpscope.app` in the desktop entry resolve.
|
application's own icon and is where the **in-process** window icon resolves from; it is also
|
||||||
|
the layout that `cmake/install_desktop_entry.cmake` mirrors when it copies the same two files
|
||||||
|
into `$XDG_DATA_HOME/icons/hicolor/scalable/apps` and `.../symbolic/apps` — those installed
|
||||||
|
copies are what makes `Icon=org.udpscope.app` in the desktop entry resolve (a desktop shell
|
||||||
|
cannot read a GResource compiled into the binary).
|
||||||
All six are bundled by `src/icons/udpscope.gresource.xml` (CMake runs
|
All six are bundled by `src/icons/udpscope.gresource.xml` (CMake runs
|
||||||
`glib-compile-resources`) and reached through **one**
|
`glib-compile-resources`) and reached through **one**
|
||||||
`gtk_icon_theme_add_resource_path()` in `run_ui()`, right after `adw_init()` — not at the top
|
`gtk_icon_theme_add_resource_path()` in `run_ui()`, right after `adw_init()` — not at the top
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ the four action icons are: udpscope is run straight out of its build tree and ha
|
|||||||
The one consequence worth knowing is that a **malformed** SVG cannot be caught at runtime -- the
|
The one consequence worth knowing is that a **malformed** SVG cannot be caught at runtime -- the
|
||||||
icon *name* still resolves, so GTK reports the icon as present and draws nothing -- which is why
|
icon *name* still resolves, so GTK reports the icon as present and draws nothing -- which is why
|
||||||
every `<file>` in the manifest carries `preprocess="xml-stripblanks"` and the build fails with a
|
every `<file>` in the manifest carries `preprocess="xml-stripblanks"` and the build fails with a
|
||||||
file, line and column instead.
|
file and line number (plus a caret under the offending character) instead.
|
||||||
|
|
||||||
**The About dialog is an `AdwAboutDialog`** rather than a `GtkAboutDialog`, and that migration is
|
**The About dialog is an `AdwAboutDialog`** rather than a `GtkAboutDialog`, and that migration is
|
||||||
what the app has an icon *for*: the dialog shows it in its own header, which `GtkAboutDialog`
|
what the app has an icon *for*: the dialog shows it in its own header, which `GtkAboutDialog`
|
||||||
@@ -313,7 +313,7 @@ cmake --build build --target desktop-entry
|
|||||||
```
|
```
|
||||||
|
|
||||||
That writes `org.udpscope.app.desktop` and both app icons under `$XDG_DATA_HOME` (default
|
That writes `org.udpscope.app.desktop` and both app icons under `$XDG_DATA_HOME` (default
|
||||||
`~/.local/share`), validates the entry with `desktop-file-validate` as a hard failure, refreshes
|
`~/.local/share`), validates the entry with `desktop-file-validate` as a hard failure when the tool is on `PATH`, refreshes
|
||||||
`update-desktop-database` and `gtk4-update-icon-cache` if they are on `PATH`, and prints the three
|
`update-desktop-database` and `gtk4-update-icon-cache` if they are on `PATH`, and prints the three
|
||||||
paths it wrote. Those three lines **are** the uninstall instructions: there is no uninstall
|
paths it wrote. Those three lines **are** the uninstall instructions: there is no uninstall
|
||||||
target, because three `rm`s the build already told you about are less to maintain than a target
|
target, because three `rm`s the build already told you about are less to maintain than a target
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
such a file outright, but the icon *name* still resolves, so `gtk_icon_theme_has_icon()`
|
such a file outright, but the icon *name* still resolves, so `gtk_icon_theme_has_icon()`
|
||||||
returns true and the icon simply draws nothing. No runtime GTK call can tell the two apart
|
returns true and the icon simply draws nothing. No runtime GTK call can tell the two apart
|
||||||
(`lookup_icon()` never returns NULL and always reports the size it was asked for), so the
|
(`lookup_icon()` never returns NULL and always reports the size it was asked for), so the
|
||||||
check belongs here, where a double hyphen inside a comment fails the build with a file,
|
check belongs here, where a malformed SVG fails the build with a file and line number
|
||||||
line and column instead.
|
(plus a caret under the offending character) instead.
|
||||||
-->
|
-->
|
||||||
<gresources>
|
<gresources>
|
||||||
<gresource prefix="/org/udpscope/icons">
|
<gresource prefix="/org/udpscope/icons">
|
||||||
|
|||||||
Reference in new issue
Block a user