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:
Martino Ferrari committed 2026-09-28 01:03:07 +02:00
1 parent b5b9b42be1
commit dc0a977c86
4 files changed
+41 -6

No files matched your search

+17 -3
View File
@@ -344,10 +344,24 @@ PLOT_TEST(imgui_widget_invalid_position_does_not_move_the_range) {
f.frame(ImVec2(-kMaxFloat, -kMaxFloat), false);
PLOT_CHECK(!f.panning());
// And a real position after the sentinel is not differenced against the sentinel.
// A drag held across a sentinel, then a real position again. The movement must be
// measured from the last *real* position -- 100 px from (200, 200) to (300, 300) --
// and not from the sentinel. This is asserted with the drag alive on purpose:
// nothing can move a range once the button is up, so the same check after the
// release could not fail and would prove nothing.
f.frame(ImVec2(200.0f, 200.0f), false);
f.frame(ImVec2(200.0f, 200.0f), true);
const plot::Range second_press = f.x_range();
f.frame(ImVec2(-kMaxFloat, -kMaxFloat), true);
PLOT_CHECK(f.panning());
const double axes_w = static_cast<double>(std::as_const(f.plot).layout().axes.w);
const double expected_shift = 100.0 / axes_w * second_press.span();
f.frame(ImVec2(300.0f, 300.0f), true);
PLOT_CHECK(f.panning());
PLOT_CHECK(std::isfinite(f.x_range().min));
PLOT_CHECK_NEAR(f.x_range().min, second_press.min - expected_shift, 0.05 * expected_shift);
f.frame(ImVec2(300.0f, 300.0f), false);
PLOT_CHECK_NEAR(f.x_range().min, pressed.min, 1e-9);
PLOT_CHECK_NEAR(f.x_range().max, pressed.max, 1e-9);
PLOT_CHECK(!f.panning());
}
PLOT_TEST(imgui_widget_paints_the_whole_child_when_nothing_clips_it) {