fix: place the guided tour's card from its allocation, and count GTK warnings
The tour measured its card with a height-for-width request whose for_size came from the natural width minus the margins the tour sets for positioning. A measure reports margins *included*, so that for_size landed a margin short of the minimum the box answers with and GTK warned once per frame: Trying to measure GtkBox 0x... for width of N, but it needs at least M (about 9/s for as long as the tour was up). The card now takes its size from gtk_widget_compute_bounds() once a frame has run -- its allocation rectangle, not gtk_widget_get_width(), which is only the content box -- and falls back to a measure with no for_size at all only on a frame with nothing allocated. GTK is built with structured logging, so its messages reach the log writer and never the handler API; no existing probe can read one. The exit dump now counts them (`gtk warnings:`, must read 0) through a writer function chained to g_log_writer_default(), which leaves stderr unchanged.
This commit is contained in:
1 parent
d8a79b96ba
commit
bb62b8178c
5 files changed
+94
-12
No files matched your search
+32
-11
@@ -296,19 +296,40 @@ void update_tour(App& app) {
|
||||
// whichever column is beside it -- which is, on this window, the side panel for the plot's step and
|
||||
// the plot for every step in the side panel.
|
||||
//
|
||||
// Its size is measured, never requested -- but `gtk_widget_measure()` reports the size *including
|
||||
// the widget's own margins* (measured: a 280 px box with `margin-start` 453 measures 733). Ours are
|
||||
// the card's position, so reading the measure without taking them off is a feedback loop: the width
|
||||
// it was placed at becomes the width it reports, and the card walks to the far corner and back
|
||||
// between frames.
|
||||
// The card's size is the *rectangle it was allocated*, read the same way the probe reads it and
|
||||
// the help's figures are drawn from: `gtk_widget_compute_bounds()`. Not `gtk_widget_get_width()`,
|
||||
// which is the widget's *content* size -- a border and a padding short of the rectangle on screen
|
||||
// (measured here: 254 against the card's real 280), so a card placed from it overhangs its own size
|
||||
// into the target; that call is read only to tell a frame that has been laid out from one that is
|
||||
// too early. And, once a frame has run, not a measure either:
|
||||
// * `gtk_widget_measure()` reports the size *including the widget's own margins* (a 280 px box
|
||||
// with `margin-start` 453 measures 733), and ours are the card's position -- reading one back
|
||||
// without taking them off is a feedback loop.
|
||||
// * asking for a **height** with a width (`for_size`) on a widget whose margins are then left out
|
||||
// of that width is a question GTK refuses: it reports `Trying to measure GtkBox ... for width
|
||||
// of N, but it needs at least M` once per frame, because the for_size derived from the natural
|
||||
// width minus the margins lands one margin short of the minimum the box answers with. The
|
||||
// allocation the widget was actually given cannot be short of it.
|
||||
// A measure survives only as the fallback for a frame with nothing allocated yet (the first frame
|
||||
// the card is shown, before any layout pass), and that fallback is taken with **no for_size at
|
||||
// all**: `for_size == -1` is the form GTK measures without the check that warns.
|
||||
int cw = 0;
|
||||
int ch = 0;
|
||||
gtk_widget_measure(app.tour_card, GTK_ORIENTATION_HORIZONTAL, -1, nullptr, &cw, nullptr, nullptr);
|
||||
cw = std::max(kCardWidth, cw - gtk_widget_get_margin_start(app.tour_card) -
|
||||
gtk_widget_get_margin_end(app.tour_card));
|
||||
gtk_widget_measure(app.tour_card, GTK_ORIENTATION_VERTICAL, cw, nullptr, &ch, nullptr, nullptr);
|
||||
ch = std::max(0, ch - gtk_widget_get_margin_top(app.tour_card) -
|
||||
gtk_widget_get_margin_bottom(app.tour_card));
|
||||
graphene_rect_t card_bounds = GRAPHENE_RECT_INIT(0, 0, 0, 0);
|
||||
if (gtk_widget_is_visible(app.tour_card) && gtk_widget_get_width(app.tour_card) > 0 &&
|
||||
gtk_widget_compute_bounds(app.tour_card, app.tour_overlay, &card_bounds)) {
|
||||
cw = static_cast<int>(std::ceil(card_bounds.size.width));
|
||||
ch = static_cast<int>(std::ceil(card_bounds.size.height));
|
||||
}
|
||||
if (cw <= 0 || ch <= 0) {
|
||||
gtk_widget_measure(app.tour_card, GTK_ORIENTATION_HORIZONTAL, -1, nullptr, &cw, nullptr,
|
||||
nullptr);
|
||||
cw = std::max(kCardWidth, cw - gtk_widget_get_margin_start(app.tour_card) -
|
||||
gtk_widget_get_margin_end(app.tour_card));
|
||||
gtk_widget_measure(app.tour_card, GTK_ORIENTATION_VERTICAL, -1, nullptr, &ch, nullptr, nullptr);
|
||||
ch = std::max(0, ch - gtk_widget_get_margin_top(app.tour_card) -
|
||||
gtk_widget_get_margin_bottom(app.tour_card));
|
||||
}
|
||||
int cx = 0, cy = 0;
|
||||
if (h - (hy + hh) >= ch + 2 * kGap) {
|
||||
cx = std::clamp(hx, kGap, std::max(kGap, w - cw - kGap));
|
||||
|
||||
Reference in new issue
Block a user