fix: a file view states its pin once, so the axis holds still
`set_data_pin()` takes a range and `pin_event_window()` a pre/post split; the file view handed the split to both. On a recording whose stamps start before zero that stored a pin that no longer held the data, so every second frame found the pin wrong and stated it in full again -- rewriting the group's x range and discarding the user's gesture with it. The view alternated between the file's span and the corrupted one at the frame rate: a flicker in which no pan, zoom or click survived. `[drop-probe]` now reports the view and the count of pin statements, which must stay at two for a whole run. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
345145c52b
commit
4235ee6225
6 files changed
+52
-6
No files matched your search
+10
-2
@@ -3392,11 +3392,19 @@ gboolean tick(gpointer user) {
|
||||
// made it a no-op. The held-event branch above has this shape for this reason: `set_data_pin()`
|
||||
// for the numbers, `pin_event_window()` when the view first becomes an event. A re-open into the
|
||||
// same row set with a different extent *is* a new event and re-states it.
|
||||
const auto pin_view = [lo, hi](RowSet& rows) {
|
||||
const auto pin_view = [lo, hi, app](RowSet& rows) {
|
||||
// `set_data_pin()` takes the **range**, `pinned_window_is()`/`pin_event_window()` the
|
||||
// pre/post split: passing the split to the former wrote the pin as `[lo, -lo]`-ish, which
|
||||
// on a recording whose stamps start *before* zero is a window that no longer holds the
|
||||
// data. The next frame's `pinned_window_is()` then read false, re-stated the pin, and the
|
||||
// view alternated between the file's span and the corrupted one every frame -- a flicker
|
||||
// with no interaction surviving it. A file whose first stamp was positive hid this: the
|
||||
// corrupted pin was wider than the data and the clamp never fired.
|
||||
if (rows.pinned_window_is(-lo, hi)) {
|
||||
rows.set_data_pin(-lo, hi);
|
||||
rows.set_data_pin(lo, hi);
|
||||
} else {
|
||||
rows.pin_event_window(-lo, hi);
|
||||
++app->dbg_file_repins;
|
||||
}
|
||||
rows.set_trigger_marker(0.0, true);
|
||||
};
|
||||
|
||||
@@ -644,6 +644,11 @@ struct App {
|
||||
/// afterwards is the glitch.
|
||||
int dbg_notrace_frames = 0;
|
||||
int dbg_notrace_last = -1;
|
||||
/// Times the file view has *stated* its pin rather than only refreshing its numbers. A file's
|
||||
/// extent does not change while it is open, so this must read **1** for a whole run: stating the
|
||||
/// pin writes the group's range, which discards whatever gesture the user had left on the axis,
|
||||
/// so a count that grows with the frames is both the flicker and the reason no interaction took.
|
||||
int dbg_file_repins = 0;
|
||||
/// The widest *minimum* width the side column or either pane has ever demanded. The side
|
||||
/// column is a fixed 320 px by design, so a figure far above that is a label whose text drove
|
||||
/// its own minimum -- the "layout must not depend on content" rule broken, and the only known
|
||||
|
||||
+9
-2
@@ -3863,10 +3863,17 @@ gboolean noise_probe_denoise(gpointer user) {
|
||||
gboolean drop_probe(gpointer user) {
|
||||
App* a = static_cast<App*>(user);
|
||||
if (a->window == nullptr || a->model->signals().empty()) return G_SOURCE_REMOVE;
|
||||
std::fprintf(stderr, "[drop-probe] signals=%zu channels=%zu rows=%d slots0=[%s|%s|%s|%s]\n",
|
||||
// `repins` beside the view: a file's extent is fixed, so the pin is stated once and only its
|
||||
// numbers are refreshed afterwards. A count that tracks the frame number is the pin being written
|
||||
// every frame, which flickers the view and swallows every gesture.
|
||||
const plot::Range view = a->rows->view_range();
|
||||
std::fprintf(stderr,
|
||||
"[drop-probe] signals=%zu channels=%zu rows=%d slots0=[%s|%s|%s|%s] "
|
||||
"view=[%.6f..%.6f] repins=%d\n",
|
||||
a->model->signals().size(), a->model->channels().size(), a->rows->row_count(),
|
||||
a->rows->row(0).name[0].c_str(), a->rows->row(0).name[1].c_str(),
|
||||
a->rows->row(0).name[2].c_str(), a->rows->row(0).name[3].c_str());
|
||||
a->rows->row(0).name[2].c_str(), a->rows->row(0).name[3].c_str(), view.min, view.max,
|
||||
a->dbg_file_repins);
|
||||
for (int signal = 0; signal < 2 && static_cast<std::size_t>(signal) < a->model->signals().size();
|
||||
++signal) {
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
Reference in new issue
Block a user