fix: the sidebar keeps its own width, so a small window can no longer hide it

The sidebar's width was a GtkPaned divider position: `window - 940` in pixels. On any window
narrower than 940 px the divider landed past the right edge and the sidebar came up 0 px wide,
reachable only by dragging the divider back.

Every attempt that kept the paned failed for that reason -- deriving the position from the paned's
own width, re-parenting the column, property-form children, code-set size requests. The mechanism was
the fault, so it is gone: the row is an AdwOverlaySplitView, which is what a utility sidebar is in
GNOME, with min-sidebar-width = max-sidebar-width = 320 in pixels. Its width is therefore its own at
any window size, and when there is no room beside the plot it *overlays* the plot (collapsed, set from
the window's width in tick()) instead of being squeezed to nothing.

Two things found on the way, both recorded in the invariants:

- sidebar-width-fraction is a 0..1 fraction of the window whatever sidebar-width-unit says. Setting a
  pixel count there is a GObject critical and it falls back to 0.25, which is why the sidebar first
  read 560. The width is pinned with min/max instead.
- the window opened at its content minimum (756 px, the plot column plus the sidebar) because the
  explicit gtk_window_set_default_size() was dropped when the window moved into the .ui. Restored.

[sidebar-probe] reads both states and is the guard: window=756 sidebar=320 under a 2x scale, which is
the case that used to read 0.
This commit is contained in:
Martino Ferrari committed 2026-10-12 12:17:56 +02:00
1 parent a8c25f0cb3
commit bb01278d88
7 files changed
+165 -54

No files matched your search

+16
View File
@@ -4,6 +4,22 @@ How `plot::Figure`/`plot::Plot` may and may not be driven, what a row's state be
Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to learn; read the ones touching the area you are editing before you edit it.
- **A sidebar's size must be its own, never a divider's position.** `GtkPaned` keeps a child's size in
`position`, which is a number of pixels **of the window**: the sidebar's width *was* `window - 940`, so on
any window narrower than 940 px — a scaled display, where the logical width is half what the screen looks
like, or a window a manager capped — the sidebar came up **0 px wide**, and the only way to see it was to
drag the divider back. Every patch that kept the paned failed for the same reason (the position derived
from the paned's own width, re-parenting the column, the property form of its children, size requests):
the *mechanism* was the fault. It is an **`AdwOverlaySplitView`** now — what a utility sidebar is in
GNOME, as against `AdwNavigationSplitView`, which is for navigation lists — with `min-sidebar-width` =
`max-sidebar-width` = 320 in **pixels**, so the width is its own at any window size, and `collapsed` (set
from the window's width in `tick()`) to *overlay* the plot when there is no room beside it rather than
being squeezed. `[sidebar-probe]` reads both states: `window=756 sidebar=320` under a 2x scale is exactly
the case that used to be zero.
- **`AdwOverlaySplitView:sidebar-width-fraction` is a 0..1 fraction of the window, whatever
`sidebar-width-unit` says.** Setting a pixel count there (320) is a `GObject` critical, and it silently
falls back to 0.25 — which reads as "the sidebar is mysteriously 560 px wide" on a wide window with no
error anywhere the build would catch. Pin the width with `min-sidebar-width`/`max-sidebar-width`.
- **A `GtkPaned`'s position is stated after both its sides are filled**, and that is a fact about the
*function's order* rather than about the window's shape, which is why it is the one part of the
window skeleton that cannot live in `main-window.ui`. `gtk_paned_set_position()` clamps against what
+17
View File
@@ -1043,6 +1043,23 @@ library measures and draws the rect in tests of its own.
defect this reading exists for, and it was invisible from the frame alone: the file view pinning its
axis from the ring each frame is what swallowed the gesture.
## `[sidebar-probe]`
```
[sidebar-probe] beside window=756 sidebar=320 collapsed=1
[sidebar-probe] overlaid window=756 sidebar=320 collapsed=1
```
`UDPSCOPE_PROBE_SIDEBAR_MS` reads the sidebar's width in both of the split view's states: beside the plot,
and **overlaid** on it (`collapsed`, which is the state a window with no room beside the plot produces).
- **`sidebar` must never be 0.** It was, for every window narrower than the 940 px the divider used to sit
at, and the pane could only be found by dragging the divider back — the report this reading exists for.
It must read its own width (320) in *both* states: `collapsed` changes where the sidebar is, never how
wide it is.
- `collapsed=1` on the `beside` line means the window is narrower than `kSidebarRoom` (900), which is the
expected reading on a scaled display, where the logical width is half what the screen looks like.
## `[prefs-probe]`
```
@@ -74,6 +74,10 @@ needs a probe that proves it *loads* and that its contents match whatever drives
| `src/ui/ui_layout.cpp` (~20 kB) | the layout editor's overlay buttons, which are positioned by code | only the buttons are template |
| `build_toolbar` (`src/ui.cpp`, ~212 lines) | the header bar's layout, with every button still wired in code | delicate: the `[udpscope] header:` probe reads its geometry |
**Done since:** the sidebar is an `AdwOverlaySplitView` (`src/ui/main-window.ui`) rather than a paned's end
child, so its width is its own 320 px and it overlays the plot instead of collapsing to zero — see
`[sidebar-probe]`.
Each of these is one change on the pattern `src/ui/ui_cursors.cpp` now follows: `ui_load()` the file, resolve
the ids, keep every value, signal and rebuild in code, and run the panel's own probe before committing.