Gated measurements #2
No files matched your search
@@ -629,3 +629,11 @@ samples. Three rules keep that honest:
|
|||||||
its ink is not in the widget's paint tree, so `gtk_snapshot_free_to_node()` on a widget paintable of
|
its ink is not in the widget's paint tree, so `gtk_snapshot_free_to_node()` on a widget paintable of
|
||||||
it returns NULL and the "screenshot" would be an empty file. Drawing it in the store also keeps that
|
it returns NULL and the "screenshot" would be an empty file. Drawing it in the store also keeps that
|
||||||
class GTK-free, which is what makes the cache testable without a window.
|
class GTK-free, which is what makes the cache testable without a window.
|
||||||
|
|
||||||
|
- **A pin is mirrored as a *range*, never as a pair of numbers that might be spans.** `Range`
|
||||||
|
(`pinned_range()`: `{-pre, +post}`) and the pin's *spans* (`pin_event_window(pre, post)`) are two
|
||||||
|
different things that both look like a pair, and mixing them inverts the window: a second view
|
||||||
|
that handed `pinned_range().min` to `pin_event_window()` pinned to `[+pre, +post]`, and the plot
|
||||||
|
drew nothing — no trace, no axis labels — because the x range was degenerate. Views that mirror a
|
||||||
|
pin use `pin_display_range(x0, x1)`, the range's own form. `[scope-probe] pin_mirror=1` reads the
|
||||||
|
two windows' pins and the scope's x range, and an inverted pin reads `0`.
|
||||||
@@ -1474,6 +1474,7 @@ a defect in the copy. Measured output:
|
|||||||
[scope-probe] gl copy=ok(67f) empty=ok(39f) empty_bound=1
|
[scope-probe] gl copy=ok(67f) empty=ok(39f) empty_bound=1
|
||||||
[scope-probe] gl detached ok=1 frames=42 rows=1 slot0='sine'
|
[scope-probe] gl detached ok=1 frames=42 rows=1 slot0='sine'
|
||||||
[scope-probe] rclick=1
|
[scope-probe] rclick=1
|
||||||
|
[scope-probe] pin_mirror=1 main=[-1.000..1.000] scope=[-1.000..1.000] x=[-1.000..1.000]
|
||||||
```
|
```
|
||||||
|
|
||||||
- `count=2` is both windows having been created and retained; `windows=1` each being a visible
|
- `count=2` is both windows having been created and retained; `windows=1` each being a visible
|
||||||
@@ -1493,6 +1494,12 @@ a defect in the copy. Measured output:
|
|||||||
signal into it" — landing in its row set. `drop=0` names a refused drop (a full plot or an
|
signal into it" — landing in its row set. `drop=0` names a refused drop (a full plot or an
|
||||||
unacquirable signal); `page_groups` less than the window count is a page rebuilt before the
|
unacquirable signal); `page_groups` less than the window count is a page rebuilt before the
|
||||||
windows were read or a group that lost its window.
|
windows were read or a group that lost its window.
|
||||||
|
- `pin_mirror=1` is a scope window **mirroring a pin as a range**: the probe pins the main window
|
||||||
|
and reads the scope's pin and its plot's x range a frame later. Both must agree and the x range
|
||||||
|
must be ordered (`x=[min..max]`, `min < max`). A `0` with an inverted scope pin (`[+pre, +post]`)
|
||||||
|
is the defect this exists for: `pin_event_window()` takes **spans**, and passing it a range's
|
||||||
|
signed `min` turned the window inside out, so a scope in Held or Paused mode drew no trace and no
|
||||||
|
x labels at all.
|
||||||
- `rclick=1` is the scope window's **own right-click menu** being wired (one click gesture with
|
- `rclick=1` is the scope window's **own right-click menu** being wired (one click gesture with
|
||||||
button 3 on its GL area, beside the drop target): the menu's actions act on that window's row
|
button 3 on its GL area, beside the drop target): the menu's actions act on that window's row
|
||||||
set.
|
set.
|
||||||
|
|||||||
@@ -1509,6 +1509,19 @@ void RowSet::pin_event_window(double pre_s, double post_s) {
|
|||||||
figure_->set_x_link_range(x_group_, {-pre_s, post_s});
|
figure_->set_x_link_range(x_group_, {-pre_s, post_s});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RowSet::pin_display_range(double x0, double x1) {
|
||||||
|
if (!(x1 > x0)) return;
|
||||||
|
window_s_ = std::max(1.0e-3, x1 - x0);
|
||||||
|
pinned_ = true;
|
||||||
|
pinned_pre_ = -x0;
|
||||||
|
pinned_post_ = x1;
|
||||||
|
if (!figure_) return;
|
||||||
|
// The same two statements `pin_event_window()` makes, from the range instead of the spans: the
|
||||||
|
// group stops following the live edge and is placed on the event's own window.
|
||||||
|
figure_->set_x_link_follow(x_group_, plot::XFollow::Off);
|
||||||
|
figure_->set_x_link_range(x_group_, {x0, x1});
|
||||||
|
}
|
||||||
|
|
||||||
void RowSet::fit_all() {
|
void RowSet::fit_all() {
|
||||||
for (int i = 0; i < rows_; ++i) {
|
for (int i = 0; i < rows_; ++i) {
|
||||||
Row& r = row(i);
|
Row& r = row(i);
|
||||||
|
|||||||
@@ -570,6 +570,13 @@ class RowSet {
|
|||||||
/// 0, so nothing outside the pre+post window is visible.
|
/// 0, so nothing outside the pre+post window is visible.
|
||||||
void pin_event_window(double pre_s, double post_s);
|
void pin_event_window(double pre_s, double post_s);
|
||||||
|
|
||||||
|
/// The same pin, stated as the **range** a second view mirrors: the caller has the display
|
||||||
|
/// range (`x0 < x1`) and not the spans -- a scope window takes `pinned_range()` from the main
|
||||||
|
/// window and hands it on. `pin_event_window()` takes *spans*, and passing it a range's signed
|
||||||
|
/// `min` turned the pin inside out (a scope in Held mode pinned to `[+pre, +post]`: no trace
|
||||||
|
/// and no x labels). A degenerate or inverted range pins nothing.
|
||||||
|
void pin_display_range(double x0, double x1);
|
||||||
|
|
||||||
/// Fits every row's y axis to the data it holds, and puts x back on the whole time window --
|
/// Fits every row's y axis to the data it holds, and puts x back on the whole time window --
|
||||||
/// `fit_x()`'s x half exactly, so the two cannot drift apart. Like it, **this does not change
|
/// `fit_x()`'s x half exactly, so the two cannot drift apart. Like it, **this does not change
|
||||||
/// the time window**: the y axes are fitted to their data, x is merely un-zoomed.
|
/// the time window**: the y axes are fitted to their data, x is merely un-zoomed.
|
||||||
|
|||||||
+12
-6
@@ -4633,17 +4633,23 @@ gboolean tick(gpointer user) {
|
|||||||
const double window_s = app->rows->time_window();
|
const double window_s = app->rows->time_window();
|
||||||
for (const std::unique_ptr<App::ScopeWindow>& scope : app->scopes) {
|
for (const std::unique_ptr<App::ScopeWindow>& scope : app->scopes) {
|
||||||
if (pinned) {
|
if (pinned) {
|
||||||
scope->rows->pin_event_window(pin.min, pin.max);
|
// The pin as a *range*: `pin_event_window()` takes spans (pre, post), and handing it
|
||||||
|
// `pin.min` -- a signed time -- inverted the window, so a scope in Held or Paused mode
|
||||||
|
// drew no trace and no x labels at all.
|
||||||
|
scope->rows->pin_display_range(pin.min, pin.max);
|
||||||
} else if (std::fabs(scope->rows->time_window() - window_s) > 1.0e-12) {
|
} else if (std::fabs(scope->rows->time_window() - window_s) > 1.0e-12) {
|
||||||
scope->rows->set_time_window(window_s);
|
scope->rows->set_time_window(window_s);
|
||||||
}
|
}
|
||||||
// An arrangement change (a drop, a *Plot on* button) rebuilt the row set: point the area at
|
// An arrangement change (a drop, a *Plot on* button) rebuilt the row set: point the area at
|
||||||
// the new figure here, in the tick -- the change arrives from inside this very widget (a drop
|
// the new figure here, in the tick -- the change arrives from inside this very widget (a drop
|
||||||
// signal), and a synchronous rebuild would reset the drag controller under it.
|
// signal), and a synchronous rebuild would reset the drag controller under it. The traces
|
||||||
// REPRO-TEMP: rebuild disabled
|
// themselves are `SlotSeries` rebinds, so a slot that gains or loses a source draws either
|
||||||
// if (scope->rows->rebuild_if_dirty() && scope->area != nullptr) {
|
// way; what *does* need this is the figure's own state: a row's legend, its cell structure,
|
||||||
// scope->area->set_figure(&scope->rows->figure());
|
// and the trace objects `install()` creates only for the slots that hold a signal at rebuild
|
||||||
// }
|
// time -- a window opened empty and filled by a drop has none until this runs.
|
||||||
|
if (scope->rows->rebuild_if_dirty() && scope->area != nullptr) {
|
||||||
|
scope->area->set_figure(&scope->rows->figure());
|
||||||
|
}
|
||||||
if (scope->detached) sync_scope_attach(*app, *scope);
|
if (scope->detached) sync_scope_attach(*app, *scope);
|
||||||
// **A window that cannot paint says so.** A blank plot is indistinguishable from a
|
// **A window that cannot paint says so.** A blank plot is indistinguishable from a
|
||||||
// context that failed or an area that never got a frame, and the report ("nothing is
|
// context that failed or an area that never got a frame, and the report ("nothing is
|
||||||
|
|||||||
+27
-2
@@ -1915,11 +1915,13 @@ gboolean scope_probe_step(gpointer user) {
|
|||||||
det.rows != nullptr && det.rows->row_count() > 0
|
det.rows != nullptr && det.rows->row_count() > 0
|
||||||
? det.rows->row(0).signal_name[0].c_str()
|
? det.rows->row(0).signal_name[0].c_str()
|
||||||
: "");
|
: "");
|
||||||
|
}
|
||||||
// The scope window carries its own right-click menu (its gesture is on the GL area, wired
|
// The scope window carries its own right-click menu (its gesture is on the GL area, wired
|
||||||
// beside the drop target): one click gesture whose button is 3, per window.
|
// beside the drop target): one click gesture whose button is 3, per window.
|
||||||
int right_clicks = 0;
|
int right_clicks = 0;
|
||||||
if (det.widget != nullptr) {
|
GtkWidget* det_widget = a->scopes.empty() ? nullptr : a->scopes.back()->widget;
|
||||||
GListModel* controllers = gtk_widget_observe_controllers(det.widget);
|
if (det_widget != nullptr) {
|
||||||
|
GListModel* controllers = gtk_widget_observe_controllers(det_widget);
|
||||||
const guint n = g_list_model_get_n_items(G_LIST_MODEL(controllers));
|
const guint n = g_list_model_get_n_items(G_LIST_MODEL(controllers));
|
||||||
for (guint i = 0; i < n; ++i) {
|
for (guint i = 0; i < n; ++i) {
|
||||||
GObject* c = G_OBJECT(g_list_model_get_item(controllers, i));
|
GObject* c = G_OBJECT(g_list_model_get_item(controllers, i));
|
||||||
@@ -1933,8 +1935,31 @@ gboolean scope_probe_step(gpointer user) {
|
|||||||
}
|
}
|
||||||
std::fprintf(stderr, "[scope-probe] rclick=%d\n", right_clicks);
|
std::fprintf(stderr, "[scope-probe] rclick=%d\n", right_clicks);
|
||||||
std::fflush(stderr);
|
std::fflush(stderr);
|
||||||
|
// **The pin mirror**: a held event pins the main window, and every scope must be pinned to
|
||||||
|
// the *same range*. `pin_event_window()` takes spans (pre, post) and passing it a range's
|
||||||
|
// signed min turned the pin inside out (a scope in Held drew no trace and no x labels).
|
||||||
|
a->rows->pin_event_window(1.6, 0.4);
|
||||||
|
a->dbg_scope_step = 4;
|
||||||
|
g_timeout_add(350, scope_probe_step, a);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
case 4: {
|
||||||
|
const plot::Range main_pin = a->rows->pinned_range();
|
||||||
|
const plot::Range scope_pin = a->scopes[0]->rows->pinned_range();
|
||||||
|
const plot::Range scope_x = a->scopes[0]->rows->row(0).plot != nullptr
|
||||||
|
? a->scopes[0]->rows->row(0).plot->x_range(0)
|
||||||
|
: plot::Range{};
|
||||||
|
const bool pinned = a->scopes[0]->rows->window_pinned() == a->rows->window_pinned();
|
||||||
|
const bool same = std::fabs(scope_pin.min - main_pin.min) < 1e-9 &&
|
||||||
|
std::fabs(scope_pin.max - main_pin.max) < 1e-9 &&
|
||||||
|
scope_x.max > scope_x.min;
|
||||||
|
std::fprintf(stderr,
|
||||||
|
"[scope-probe] pin_mirror=%d main=[%.3f..%.3f] scope=[%.3f..%.3f] "
|
||||||
|
"x=[%.3f..%.3f]\n",
|
||||||
|
pinned && same ? 1 : 0, main_pin.min, main_pin.max, scope_pin.min,
|
||||||
|
scope_pin.max, scope_x.min, scope_x.max);
|
||||||
std::fflush(stderr);
|
std::fflush(stderr);
|
||||||
|
a->rows->set_time_window(2.0); // unpin: leave the window as the run found it
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in new issue
Block a user