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:
1 parent
a8c25f0cb3
commit
bb01278d88
7 files changed
+165
-54
No files matched your search
+52
-46
@@ -2,46 +2,67 @@
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
<!-- SPDX-FileCopyrightText: 2026 Martino Ferrari -->
|
||||
<!--
|
||||
The main window's skeleton: the window, the two panes that make its three columns, the plot column
|
||||
with the status line under it, and the sidebar's scroller.
|
||||
The main window's skeleton: the window, the split view that puts the sidebar beside the plot, the
|
||||
events pane's divider, the plot column with the status line under it, and the sidebar's scroller.
|
||||
|
||||
The sidebar is an `AdwOverlaySplitView`, which is what a utility sidebar is in GNOME (as against
|
||||
`AdwNavigationSplitView`, which is for navigation lists). Three things follow from that, and they are
|
||||
the reasons it is here:
|
||||
|
||||
- its width is *its own*: `sidebar-width-fraction` in **pixels** (the unit says so), floored by
|
||||
`min-sidebar-width`. A `GtkPaned` kept a child's size in a divider position, which is a number of
|
||||
pixels *of the window* — so on a window narrower than that number the sidebar came up with no
|
||||
width at all, which is the bug this widget replaces;
|
||||
- it resizes by dragging its own edge, within `min-sidebar-width`..`max-sidebar-width`;
|
||||
- when the window is too narrow for both columns it *overlays* the plot instead of squeezing it,
|
||||
which is what `collapsed` is for; `tick()` sets it from the window's width.
|
||||
|
||||
What is *not* here is as deliberate as what is. Everything this file nests is fixed — the shape of
|
||||
the window does not depend on the stream, the trigger or the layout — while the four subtrees that
|
||||
do are built by code and put in place:
|
||||
the window does not depend on the stream, the trigger or the layout — while the subtrees that do are
|
||||
built by code and put in place: the events pane, into `events_divider`'s start side; the two plot
|
||||
areas, into the split inside `plot_box`; the sidebar's panels, appended to `side_column`; and the
|
||||
status popover, attached to `status_info`.
|
||||
|
||||
- the events pane, into the inner paned's start side;
|
||||
- the two plot areas, into the split inside `plot_box`;
|
||||
- the sidebar's panels, appended to `side_column`;
|
||||
- the status popover, attached to `status_info`.
|
||||
|
||||
A `GtkApplicationWindow` and not an `AdwApplicationWindow`, deliberately: the header bar is the
|
||||
window's own titlebar and Adw's window refuses one outright (`gtk_window_set_titlebar() is not
|
||||
supported for AdwApplicationWindow`, which is a fatal `Adwaita-ERROR`, not a warning). An Adw window
|
||||
would want its header as an `AdwToolbarView`'s top bar instead, and this one is a `GtkHeaderBar`
|
||||
packed by hand — a change for its own sake, and one that would take the window controls away from it
|
||||
(a GtkHeaderBar draws those only as a titlebar).
|
||||
|
||||
The header bar is *not* in this file: it is the window's own titlebar,
|
||||
built by `build_toolbar()` because every button on it is wired to an action. The status line is not a
|
||||
bottom bar either — it belongs to the plot column, not to the window, so it stays inside `left_column`
|
||||
where the paned divider can move past it.
|
||||
|
||||
The `GtkPaned`s are here rather than in code because their *rules* are the skeleton: the events pane
|
||||
is shrinkable and does not resize (so a closed pane costs the plot nothing), and the sidebar is
|
||||
neither. `gtk_paned_set_position()` is not, because it has to run after the children exist.
|
||||
The header bar is not here either: it is the window's own titlebar, built by `build_toolbar()`
|
||||
because every button on it is wired to an action. The status line is not a bottom bar — it belongs to
|
||||
the plot column, not to the window, so it stays inside `left_column` where the divider can move past
|
||||
it.
|
||||
-->
|
||||
<interface>
|
||||
<object class="GtkApplicationWindow" id="main_window">
|
||||
<property name="title">udpscope</property>
|
||||
<property name="icon-name">org.udpscope.app</property>
|
||||
<!-- The size the window asks for, stated in code as well as here: a window whose content has a
|
||||
larger minimum opens at that minimum instead (see `ui.cpp`). -->
|
||||
<property name="default-width">1280</property>
|
||||
<property name="default-height">800</property>
|
||||
<child>
|
||||
<object class="GtkPaned" id="paned">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="resize-end-child">0</property>
|
||||
<property name="shrink-end-child">0</property>
|
||||
<child type="start">
|
||||
<object class="AdwOverlaySplitView" id="side_view">
|
||||
<property name="sidebar-position">end</property>
|
||||
<!-- Its width in pixels, not as a fraction of the window: 320 on a first run, and never less
|
||||
than 240 however small the window gets. -->
|
||||
<!-- Both ends of the range, in pixels: `sidebar-width-fraction` is a 0..1 *fraction* of the
|
||||
window (setting a pixel count there is a GObject critical and falls back to 0.25), so the
|
||||
width is pinned by min and max instead. -->
|
||||
<property name="sidebar-width-unit">px</property>
|
||||
<property name="min-sidebar-width">320</property>
|
||||
<property name="max-sidebar-width">320</property>
|
||||
<property name="sidebar">
|
||||
<!-- The column scrolls as a whole, so a long signal list or a revealed trigger panel can
|
||||
never push either panel out of the window. -->
|
||||
<object class="GtkScrolledWindow" id="side_scroll">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="min-content-width">300</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="side_column">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="width-request">300</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="content">
|
||||
<object class="GtkPaned" id="events_divider">
|
||||
<property name="orientation">horizontal</property>
|
||||
<!-- Shrinkable, or the pane's own minimum is reserved as an empty column even while it is
|
||||
@@ -80,7 +101,7 @@
|
||||
<child>
|
||||
<!-- The line is rewritten every frame and its counters grow, so it is
|
||||
ellipsized: a label's minimum width is its text, and an unellipsized one
|
||||
would push the paned divider around as the numbers change. -->
|
||||
would push the divider around as the numbers change. -->
|
||||
<object class="GtkLabel" id="status_label">
|
||||
<property name="label">starting…</property>
|
||||
<property name="ellipsize">end</property>
|
||||
@@ -100,22 +121,7 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<!-- The column scrolls as a whole, so a long signal list or a revealed trigger panel can
|
||||
never push either panel out of the window. -->
|
||||
<object class="GtkScrolledWindow" id="side_scroll">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="width-request">320</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="side_column">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="width-request">300</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
Reference in new issue
Block a user