From 5bb4bd207de3938ff6d21477414ff777a25c614f Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Thu, 8 Oct 2026 10:18:44 +0200 Subject: [PATCH] fix: the marks are read a frame after the jump, so a placed count is read from the window it is on The plan's Task 8 named the search probe as its test but never extended it, and leaned on the exit dump instead -- which stops the tick from Live, where no hit is in view, so it reads placed=0 for a correct implementation and a broken one alike. --- src/ui.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/ui.cpp b/src/ui.cpp index 27d3ae3..1c7e8ed 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -9085,6 +9085,36 @@ gboolean condition_probe(gpointer user) { /// prevent. It then steps to a hit and reports the pinned axis against it. double g_search_t0 = 0.0; +/// Reports the marks a *frame* after the jump, because that is the only moment they can be read +/// honestly: `search_jump()` publishes a pause view, but the axis it is pinned against and the +/// `view_range()` that `place_search_marks()` filters by are both settled by the frame tick, not +/// by the publish. Reading `search_marks_placed()` in the same callback as the jump would quote +/// the window the scope was on *before* it moved. +/// +/// This cannot be read from the exit dump instead. The exit probe stops the tick from `Live`, +/// where the newest window holds no hit at all, so a dump reading is `placed=0` whatever the +/// marks did -- true of a correct implementation and of a broken one alike. The dump's own line +/// asserts the thing that does survive going live: that the new cursor pool is unselectable. +gboolean search_probe_marks(gpointer user) { + App* a = static_cast(user); + if (a->window == nullptr) return G_SOURCE_REMOVE; + const plot::Range view = a->rows->view_range(); + std::size_t in_view = 0; + const double s0 = a->model->stream_at_x0(); + for (const double h : a->search.hits()) { + const double x = h - s0; + if (x >= view.min && x <= view.max) ++in_view; + } + std::fprintf(stderr, + "[search-probe] marks placed=%d of %zu in view (%zu found) locked=%d mode=%d " + "axis=[%.4f..%.4f]\n", + a->rows->search_marks_placed(), in_view, a->search.hits().size(), + a->rows->readouts_locked() ? 1 : 0, int(a->model->display_mode()), view.min, + view.max); + std::fflush(stderr); + return G_SOURCE_REMOVE; +} + gboolean search_probe_report(gpointer user) { App* a = static_cast(user); if (a->window == nullptr) return G_SOURCE_REMOVE; @@ -9123,6 +9153,7 @@ gboolean search_probe_report(gpointer user) { "[search-probe] jumped to hit 0 t=%.6f mode=%d axis=[%.4f..%.4f] pos=%d\n", a->search.hits()[0], int(a->model->display_mode()), view.min, view.max, a->search.cursor() + 1); + g_timeout_add(250, search_probe_marks, a); } std::fflush(stderr); return G_SOURCE_REMOVE;