test: explain why the zoomkeys probe reads its axes synchronously
The probe's doc-comment advised running it inside a pinned state "so the _held readings mean the other axis did not move" — but the reads happen in the same callback as the key events, so no frame can intervene and nothing can re-frame. Worse, the advice hid the real reason the read is synchronous, which is the opposite of what the pan and zoom probes do and so invites a future reader to "fix" it: hold_pinned_window() clamps the x span into the pinned window, so a reading taken a frame later would report that clamp's answer rather than the restriction's for the ctrl case. Name the actual bug class a deferred read would confuse it with, and point at the probe that does assert figure adoption. std::fabs for the two span comparisons, matching the file's existing idiom — <cstdlib> is also in scope here.
This commit is contained in:
1 parent
dc7821a504
commit
856f538681
1 file changed
+12
-4
+12
-4
@@ -7182,8 +7182,16 @@ gboolean measures_probe_step(gpointer user) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Drives the plot's keyboard zoom with Ctrl and with Alt and reports which axis moved.
|
/// Drives the plot's keyboard zoom with Ctrl and with Alt and reports which axis moved.
|
||||||
/// Run it inside a pinned state (the pause probe makes a stable one) so the `_held`
|
/// The ranges are read **synchronously**, in this callback, which is deliberate and is the
|
||||||
/// readings mean "the other axis did not move", not "the frame re-framed anyway":
|
/// opposite of what the pan and zoom probes do. The question here is only "does the
|
||||||
|
/// controller's modifier restriction reach the app", so the read has to see the
|
||||||
|
/// controller's own write and nothing else: `hold_pinned_window()` clamps the *x* span
|
||||||
|
/// into the pinned window, so a reading taken a frame later would report that clamp's
|
||||||
|
/// answer rather than the restriction's for the ctrl case. Nor can a same-callback read
|
||||||
|
/// drift past a state boundary, which is the hazard the read-in-the-tick rule exists for.
|
||||||
|
/// Whether a zoom the controller performed is then *adopted* by the figure is a different
|
||||||
|
/// question, and `[pan-probe]`'s `zoom-in asked=/group=/member=` line is what asserts it.
|
||||||
|
/// Pausing first is therefore not required, only tidy — it is how Task 11 runs it:
|
||||||
/// UDPSCOPE_PROBE_PAUSE_MS=1500 UDPSCOPE_PROBE_ZOOMKEYS_MS=2200
|
/// UDPSCOPE_PROBE_PAUSE_MS=1500 UDPSCOPE_PROBE_ZOOMKEYS_MS=2200
|
||||||
gboolean zoomkeys_probe(gpointer user) {
|
gboolean zoomkeys_probe(gpointer user) {
|
||||||
App* a = static_cast<App*>(user);
|
App* a = static_cast<App*>(user);
|
||||||
@@ -7206,13 +7214,13 @@ gboolean zoomkeys_probe(gpointer user) {
|
|||||||
static_cast<plot::u32>(plot::input::Mod::Ctrl), true});
|
static_cast<plot::u32>(plot::input::Mod::Ctrl), true});
|
||||||
const plot::Range x1 = p.x_range(ax);
|
const plot::Range x1 = p.x_range(ax);
|
||||||
const plot::Range y1 = p.y_range(ay);
|
const plot::Range y1 = p.y_range(ay);
|
||||||
const int y_held = std::abs(y1.span() - y0.span()) < 1e-9 ? 1 : 0;
|
const int y_held = std::fabs(y1.span() - y0.span()) < 1e-9 ? 1 : 0;
|
||||||
|
|
||||||
c->on_key({plot::input::kKeyZoomIn,
|
c->on_key({plot::input::kKeyZoomIn,
|
||||||
static_cast<plot::u32>(plot::input::Mod::Alt), true});
|
static_cast<plot::u32>(plot::input::Mod::Alt), true});
|
||||||
const plot::Range x2 = p.x_range(ax);
|
const plot::Range x2 = p.x_range(ax);
|
||||||
const plot::Range y2 = p.y_range(ay);
|
const plot::Range y2 = p.y_range(ay);
|
||||||
const int x_held = std::abs(x2.span() - x1.span()) < 1e-9 ? 1 : 0;
|
const int x_held = std::fabs(x2.span() - x1.span()) < 1e-9 ? 1 : 0;
|
||||||
|
|
||||||
std::fprintf(stderr,
|
std::fprintf(stderr,
|
||||||
"[zoomkeys] ctrl+plus x=[%.4f..%.4f]->[%.4f..%.4f] y_held=%d | "
|
"[zoomkeys] ctrl+plus x=[%.4f..%.4f]->[%.4f..%.4f] y_held=%d | "
|
||||||
|
|||||||
Reference in new issue
Block a user