pub const PIXELS_PER_NOTCH: f64 = 40.0;
pub const NOTCHES_PER_PAGE: f64 = 8.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WheelDeltaMode {
Pixel,
Line,
Page,
}
impl WheelDeltaMode {
pub fn from_dom(delta_mode: u32) -> WheelDeltaMode {
match delta_mode {
1 => WheelDeltaMode::Line,
2 => WheelDeltaMode::Page,
_ => WheelDeltaMode::Pixel,
}
}
}
pub fn to_notches(delta: f64, mode: WheelDeltaMode) -> f64 {
if !delta.is_finite() {
return 0.0;
}
match mode {
WheelDeltaMode::Pixel => delta / PIXELS_PER_NOTCH,
WheelDeltaMode::Line => delta,
WheelDeltaMode::Page => delta * NOTCHES_PER_PAGE,
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct WheelNormalizer;
impl WheelNormalizer {
pub fn new() -> WheelNormalizer {
WheelNormalizer
}
pub fn normalize(&mut self, delta_x: f64, delta_y: f64, mode: WheelDeltaMode) -> (f64, f64) {
(to_notches(delta_x, mode), to_notches(delta_y, mode))
}
pub fn reset(&mut self) {}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reset_is_a_harmless_no_op() {
let mut n = WheelNormalizer::new();
assert_eq!(n.normalize(0.0, 4.0, WheelDeltaMode::Pixel), (0.0, 0.1));
n.reset();
assert_eq!(n.normalize(0.0, 4.0, WheelDeltaMode::Pixel), (0.0, 0.1));
}
#[test]
fn one_notch_in_each_mode() {
let mut n = WheelNormalizer::new();
assert_eq!(n.normalize(0.0, 100.0, WheelDeltaMode::Pixel).1, 2.5);
assert_eq!(n.normalize(0.0, 3.0, WheelDeltaMode::Line).1, 3.0);
assert_eq!(
n.normalize(0.0, 1.0, WheelDeltaMode::Page).1,
NOTCHES_PER_PAGE
);
}
#[test]
fn sub_notch_deltas_pass_through_fractionally() {
let mut n = WheelNormalizer::new();
for _ in 0..10 {
assert_eq!(n.normalize(0.0, 4.0, WheelDeltaMode::Pixel).1, 0.1);
}
let mut fine = WheelNormalizer::new();
let total: f64 = (0..400)
.map(|_| fine.normalize(0.0, 1.0, WheelDeltaMode::Pixel).1)
.sum();
assert!((total - 10.0).abs() < 1e-9, "{total}");
let mut coarse = WheelNormalizer::new();
assert_eq!(coarse.normalize(0.0, 400.0, WheelDeltaMode::Pixel).1, 10.0);
}
#[test]
fn direction_changes_and_axes_are_independent() {
let mut n = WheelNormalizer::new();
assert_eq!(n.normalize(0.0, 30.0, WheelDeltaMode::Pixel).1, 0.75);
assert_eq!(n.normalize(0.0, -30.0, WheelDeltaMode::Pixel).1, -0.75);
assert_eq!(n.normalize(30.0, 20.0, WheelDeltaMode::Pixel), (0.75, 0.5));
assert_eq!(n.normalize(10.0, 0.0, WheelDeltaMode::Pixel), (0.25, 0.0));
}
#[test]
fn non_finite_deltas_are_ignored() {
let mut n = WheelNormalizer::new();
assert_eq!(
n.normalize(f64::NAN, f64::INFINITY, WheelDeltaMode::Pixel),
(0.0, 0.0)
);
assert_eq!(n.normalize(0.0, 40.0, WheelDeltaMode::Pixel).1, 1.0);
}
#[test]
fn dom_delta_modes_map_across() {
assert_eq!(WheelDeltaMode::from_dom(0), WheelDeltaMode::Pixel);
assert_eq!(WheelDeltaMode::from_dom(1), WheelDeltaMode::Line);
assert_eq!(WheelDeltaMode::from_dom(2), WheelDeltaMode::Page);
assert_eq!(WheelDeltaMode::from_dom(7), WheelDeltaMode::Pixel);
}
}