improved perfs and event management

This commit is contained in:
Martino Ferrari committed 2026-10-13 23:00:42 +02:00
1 parent 667ed0c100
commit bb99be5889
17 files changed
+626 -59

No files matched your search

+70 -6
View File
@@ -1892,8 +1892,13 @@ gboolean layout_probe_step(gpointer user) {
gboolean enable_all_probe(gpointer user) {
App* a = static_cast<App*>(user);
for (std::size_t i = 0; i < a->model->signals().size(); ++i) {
a->model->set_signal_enabled(i, true);
// In one call, the way a restored session does it: enabling them one at a time re-plans
// the buffer per signal, so a probe that did that would not be measuring the path a real
// start takes (and `[gen]` would read a burst that the application no longer produces).
{
std::vector<std::size_t> all(a->model->signals().size());
for (std::size_t i = 0; i < all.size(); ++i) all[i] = i;
a->model->set_signals_enabled(all, true);
}
int row = 0;
int slot = 0;
@@ -1908,8 +1913,12 @@ gboolean enable_all_probe(gpointer user) {
}
}
a->relayout_pending = true;
std::fprintf(stderr, "[enable-all-probe] %zu channel(s) enabled and assigned to plots\n",
a->model->channel_count());
// The startup notice comes with the reading, because it is the window's only answer to "why is
// nothing happening yet": it is set as the window is presented, before the first CONFIG can take
// the model's mutex, and it names the buffer being planned. An empty `notice` here is the window
// that used to come up silent while a large buffer was allocated.
std::fprintf(stderr, "[enable-all-probe] %zu channel(s) enabled and assigned to plots, notice='%s'\n",
a->model->channel_count(), a->notice.c_str());
std::fflush(stderr);
// Then switch one off through its own switch in the signal list: a disabled signal must leave the plots,
// not sit there drawing nothing in a slot a live one could take. Late enough that a math probe armed behind
@@ -3158,6 +3167,40 @@ gboolean events_probe_step(gpointer user) {
}
if (a->dbg_events_step == 1) {
// The preview's repair, measured before anything else reads the pane: the newest event's picture
// is deleted and the pane refreshed, so the row that comes back proves the pane draws it again
// from the samples rather than showing a blank. The stored geometry is read back too, because the
// defect this fixes was a readable *file* that was too short to read -- `strip_h * signals` says
// the picture grew with the signal count, a fixed 160 says it did not.
const std::vector<EventRecord> before = a->event_store->list();
if (!before.empty()) {
const std::string bmp = a->event_store->dir() + "/" + before.front().stem + ".bmp";
::remove(bmp.c_str());
// The decoded picture has to go with the file: the cache answers by path and would hand back
// the texture of a file that is no longer there, so the refresh would never reach the repair.
if (EventThumbCache* cache = event_thumb_cache(*a)) {
for (auto& entry : *cache) {
if (entry.second != nullptr) g_object_unref(entry.second);
}
cache->clear();
}
refresh_events_pane(*a);
int w = -1;
int h = -1;
if (std::FILE* f = std::fopen(bmp.c_str(), "rb"); f != nullptr) {
unsigned char head[26] = {};
if (std::fread(head, 1, sizeof(head), f) == sizeof(head)) {
w = int(head[18]) | int(head[19]) << 8 | int(head[20]) << 16;
h = int(head[22]) | int(head[23]) << 8 | int(head[24]) << 16;
}
std::fclose(f);
}
const bool drawn = a->events_thumb != nullptr &&
gtk_picture_get_paintable(GTK_PICTURE(a->events_thumb)) != nullptr;
std::fprintf(stderr, "[events] preview redrawn: signals=%zu stored=%dx%d row_drawn=%d\n",
before.front().signals, w, h, drawn ? 1 : 0);
std::fflush(stderr);
}
const std::vector<EventRecord> records = a->event_store->list();
std::fprintf(stderr, "[events] dir=%s n=%zu", a->event_store->dir().c_str(), records.size());
if (!records.empty()) {
@@ -3185,6 +3228,18 @@ gboolean events_probe_step(gpointer user) {
// "framed" from "untouched".
apply_time_window(*a, 0.5);
GtkListBoxRow* row = gtk_list_box_get_row_at_index(GTK_LIST_BOX(a->events_list), 0);
// Selected *and* remembered, because what the activation must not do is rebuild the list:
// a selection the user made for a comparison, and the row object itself, are what a
// rebuild silently discarded. Two rows, so the reading after the click can say the
// selection survived rather than merely that something is selected.
if (row != nullptr) gtk_list_box_select_row(GTK_LIST_BOX(a->events_list), row);
if (GtkListBoxRow* second = gtk_list_box_get_row_at_index(GTK_LIST_BOX(a->events_list), 1)) {
gtk_list_box_select_row(GTK_LIST_BOX(a->events_list), second);
}
a->dbg_events_row0 = row;
GList* chosen = gtk_list_box_get_selected_rows(GTK_LIST_BOX(a->events_list));
a->dbg_events_selected = int(g_list_length(chosen));
g_list_free(chosen);
if (row != nullptr) g_signal_emit_by_name(a->events_list, "row-activated", row);
}
// One layout pass before the picture is measured: a widget created a moment ago has no
@@ -3198,10 +3253,18 @@ gboolean events_probe_step(gpointer user) {
// is set, so a non-null one says nothing about whether anything is on screen.
const bool picture = a->events_thumb != nullptr &&
gtk_picture_get_paintable(GTK_PICTURE(a->events_thumb)) != nullptr;
// The row *object*, not its index: a rebuilt list has a row 0 too, so only identity tells a
// list that was left alone from one that was torn down and refilled under the user's scroll.
const bool rows_kept =
a->dbg_events_row0 != nullptr &&
gtk_list_box_get_row_at_index(GTK_LIST_BOX(a->events_list), 0) == a->dbg_events_row0;
GList* still = gtk_list_box_get_selected_rows(GTK_LIST_BOX(a->events_list));
const int selected_now = int(g_list_length(still));
g_list_free(still);
std::fprintf(stderr,
"[events] activated row0: replaying=%d pane=%d pane_w=%d pane_box=%d tick=%d "
"window=%.3f axis=[%.3f,%.3f] marker=%.3f "
"thumbnail=%d thumb_size=%dx%d thumb_visible=%d\n",
"thumbnail=%d thumb_size=%dx%d thumb_visible=%d rows_kept=%d selected=%d/%d\n",
a->replaying ? 1 : 0,
a->events_revealer != nullptr && gtk_widget_get_visible(a->events_revealer) ? 1 : 0,
a->events_divider != nullptr ? gtk_paned_get_position(GTK_PANED(a->events_divider))
@@ -3226,7 +3289,8 @@ gboolean events_probe_step(gpointer user) {
picture ? 1 : 0,
a->events_thumb != nullptr ? gtk_widget_get_width(a->events_thumb) : -1,
a->events_thumb != nullptr ? gtk_widget_get_height(a->events_thumb) : -1,
a->events_thumb != nullptr && gtk_widget_get_mapped(a->events_thumb) ? 1 : 0);
a->events_thumb != nullptr && gtk_widget_get_mapped(a->events_thumb) ? 1 : 0,
rows_kept ? 1 : 0, selected_now, a->dbg_events_selected);
std::fflush(stderr);
events_probe_next(*a, 2, 1200);
return G_SOURCE_REMOVE;