fix: the sidebar button follows the panel, and the wish survives having no source
The toolbar button was the panel's only input: `update_side_visibility()` derived the panel from the button and never the other way, so the button went on saying "shown" in two cases where the panel was off -- while there were no signals to show, and after anything else moved the split view's state. Binding the two together is not the fix. AdwOverlaySplitView writes `show-sidebar` itself, at startup and when it collapses, with no user involved; a binding pushes that into the button, the button's handler reads it as the user's wish, and the sidebar then never comes back when a source connects -- a worse bug than the one reported, and one that a "was this our own write" flag does not catch either, because the toggle's signal may fire after the write returns. So the direction is stated instead of inferred: `show-sidebar` is an output, the button is the only input, and `App::sidebar_wanted` holds the wish between them. The wish is written by the toggle's handler alone (guarded while we set the button ourselves), the no-signals case forces the panel off without touching the wish, and tick() re-asserts both from the wish when the widget disagrees -- so a hide gesture does not stick either. [sidebar-probe] now reads the pair (shown vs button) in both states and against a hide that did not come from the button; shown=1 button=1 with a source, shown=0 button=0 without, and the source reconnecting brings both back is the reading this exists for.
This commit is contained in:
1 parent
bb01278d88
commit
2d9f327da7
5 files changed
+95
-16
No files matched your search
+27
-7
@@ -1634,7 +1634,8 @@ gboolean boxzoom_probe(gpointer user) {
|
||||
}
|
||||
|
||||
|
||||
/// `UDPSCOPE_PROBE_SIDEBAR_MS`: the sidebar's width, in both of the split view's states.
|
||||
/// `UDPSCOPE_PROBE_SIDEBAR_MS`: the sidebar's width and whether the toolbar button agrees with it, in
|
||||
/// both of the split view's states and against a hide that did not come from the button.
|
||||
///
|
||||
/// The small-window case is the one a divider position got wrong: with the sidebar's width derived from
|
||||
/// the window, a window narrower than that number gave it nothing at all. The split view takes its size
|
||||
@@ -1644,24 +1645,43 @@ gboolean boxzoom_probe(gpointer user) {
|
||||
gboolean sidebar_probe(gpointer user) {
|
||||
App& a = *static_cast<App*>(user);
|
||||
if (a.side_view == nullptr) return G_SOURCE_REMOVE;
|
||||
// `shown` is the panel's own state and `button` the toolbar's; they must agree, or the button is
|
||||
// telling the user something the window does not do.
|
||||
const auto report = [](App& app, const char* what) {
|
||||
const int side = app.side_box != nullptr ? gtk_widget_get_width(app.side_box) : -1;
|
||||
const int win = app.window != nullptr ? gtk_widget_get_width(app.window) : -1;
|
||||
std::fprintf(stderr, "[sidebar-probe] %-10s window=%d sidebar=%d collapsed=%d\n", what, win,
|
||||
side, adw_overlay_split_view_get_collapsed(ADW_OVERLAY_SPLIT_VIEW(app.side_view)) ? 1
|
||||
: 0);
|
||||
std::fprintf(stderr,
|
||||
"[sidebar-probe] %-10s window=%d sidebar=%d collapsed=%d shown=%d button=%d(sens=%d)\n",
|
||||
what, win, side,
|
||||
adw_overlay_split_view_get_collapsed(ADW_OVERLAY_SPLIT_VIEW(app.side_view)) ? 1 : 0,
|
||||
adw_overlay_split_view_get_show_sidebar(ADW_OVERLAY_SPLIT_VIEW(app.side_view)) ? 1 : 0,
|
||||
app.sidebar_toggle != nullptr &&
|
||||
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(app.sidebar_toggle)) ? 1 : 0,
|
||||
app.sidebar_toggle != nullptr && gtk_widget_get_sensitive(app.sidebar_toggle) ? 1 : 0);
|
||||
};
|
||||
report(a, "beside");
|
||||
// The state a window with no room produces: the sidebar goes over the plot, and its width is still its
|
||||
// own. If this ever reads 0, the sidebar is being given a share of a width that is not there.
|
||||
adw_overlay_split_view_set_collapsed(ADW_OVERLAY_SPLIT_VIEW(a.side_view), TRUE);
|
||||
// A hide that did not come from the button -- an overlay swipe, or the split view's own collapsing --
|
||||
// must not win: the panel is where the button says it is. `shown` and `button` still reading 1 here is
|
||||
// the point, and reading 0 is the regression (a button that no longer reflects the panel, or a panel
|
||||
// that slips out from under it).
|
||||
adw_overlay_split_view_set_show_sidebar(ADW_OVERLAY_SPLIT_VIEW(a.side_view), FALSE);
|
||||
g_timeout_add(400, +[](gpointer u) -> gboolean {
|
||||
App& app = *static_cast<App*>(u);
|
||||
const int side = app.side_box != nullptr ? gtk_widget_get_width(app.side_box) : -1;
|
||||
std::fprintf(stderr, "[sidebar-probe] %-10s window=%d sidebar=%d collapsed=%d\n", "overlaid",
|
||||
app.window != nullptr ? gtk_widget_get_width(app.window) : -1, side,
|
||||
adw_overlay_split_view_get_collapsed(ADW_OVERLAY_SPLIT_VIEW(app.side_view)) ? 1 : 0);
|
||||
std::fprintf(stderr,
|
||||
"[sidebar-probe] %-10s window=%d sidebar=%d collapsed=%d shown=%d button=%d(sens=%d)\n",
|
||||
"regained", app.window != nullptr ? gtk_widget_get_width(app.window) : -1, side,
|
||||
adw_overlay_split_view_get_collapsed(ADW_OVERLAY_SPLIT_VIEW(app.side_view)) ? 1 : 0,
|
||||
adw_overlay_split_view_get_show_sidebar(ADW_OVERLAY_SPLIT_VIEW(app.side_view)) ? 1 : 0,
|
||||
app.sidebar_toggle != nullptr &&
|
||||
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(app.sidebar_toggle)) ? 1 : 0,
|
||||
app.sidebar_toggle != nullptr && gtk_widget_get_sensitive(app.sidebar_toggle) ? 1 : 0);
|
||||
adw_overlay_split_view_set_collapsed(ADW_OVERLAY_SPLIT_VIEW(app.side_view), FALSE);
|
||||
// Back the way a person would: pressing the button is what records the wish, and the panel follows it.
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(app.sidebar_toggle), TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}, &a);
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
Reference in new issue
Block a user