fix(input): refuse a non-finite wheel amount instead of zeroing it
Zeroing an unusable wheel amount turned it into a zero-notch zoom: the factor was exactly one, the range did not change, but the zoom body still ran through set_x_range/set_y_range, which clear auto_scale unconditionally. One garbage wheel therefore disarmed auto-fit on every axis. on_wheel now rejects an unusable amount before the event can mutate anything, keeping the position fallback. The tests that should have caught it are strengthened: the wheel case now asserts auto scale is still armed (it was passing either way), and the invalid-position case checks a pan measured from the last real position with the drag alive, rather than a range nothing could have moved.
This commit is contained in:
1 parent
b5b9b42be1
commit
dc0a977c86
4 files changed
+41
-6
No files matched your search
@@ -66,14 +66,16 @@ PointerEvent sanitized(const PointerEvent& e, bool have_pointer, f32 last_x,
|
||||
return in;
|
||||
}
|
||||
|
||||
/// `e`, with an unusable position replaced by the last known one. The wheel's
|
||||
/// amount is deliberately left alone: `on_wheel` rejects an unusable one *before*
|
||||
/// the event is acted on, because a zeroed amount is a zoom of exactly one, and
|
||||
/// running that over an unchanged range would still clear every axis' auto scale.
|
||||
WheelEvent sanitized(const WheelEvent& e, bool have_pointer, f32 last_x, f32 last_y) noexcept {
|
||||
WheelEvent in = e;
|
||||
if (!finite(in.x) || !finite(in.y)) {
|
||||
in.x = have_pointer ? last_x : 0.0f;
|
||||
in.y = have_pointer ? last_y : 0.0f;
|
||||
}
|
||||
if (!finite(in.dx)) in.dx = 0.0f;
|
||||
if (!finite(in.dy)) in.dy = 0.0f;
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -106,6 +108,13 @@ void Controller::on_pointer(const PointerEvent& raw) {
|
||||
}
|
||||
|
||||
void Controller::on_wheel(const WheelEvent& raw) {
|
||||
// An amount that is not a number is not a wheel: sanitising it to zero would look
|
||||
// like a zero-notch zoom -- a factor of exactly one -- and the zoom body would
|
||||
// still run, calling the range setters with the unchanged range. Those clear
|
||||
// `auto_scale` unconditionally, so a single garbage wheel would silently disarm
|
||||
// auto-fit on every axis. Return before the event can mutate anything.
|
||||
if (!std::isfinite(raw.dy)) return;
|
||||
|
||||
const WheelEvent e = sanitized(raw, has_pointer_, pointer_x_, pointer_y_);
|
||||
plot_->layout();
|
||||
const f64 factor = zoom_factor(static_cast<f64>(e.dy));
|
||||
|
||||
Reference in new issue
Block a user