fix(app): normalize trackpad scroll deltas on macOS (#694)

This commit is contained in:
LynithDev 2026-08-19 15:07:15 +02:00
parent bd7124c873
commit ff22c8ac3b

View file

@ -5,6 +5,30 @@ use crate::theme::colors;
const LAZY_OVERSCAN: i64 = 3;
pub(crate) fn normalize_wheel_delta(delta: f64, scale_factor: f64) -> f32 {
if delta == 0.0 {
return 0.0;
}
const FREYA_LINE_SPEED: f64 = 53.0;
const FREYA_PIXEL_SPEED: f64 = 2.0;
const LINE_DELTA_TOLERANCE: f64 = 1e-6;
const LINE_SCROLL: f64 = 53.0;
const PIXEL_SCROLL: f64 = 1.0;
let lines = (delta / FREYA_LINE_SPEED).round();
if lines != 0.0 && (delta - lines * FREYA_LINE_SPEED).abs() <= LINE_DELTA_TOLERANCE {
return (lines * LINE_SCROLL) as f32;
}
let scale_factor = if scale_factor > 0.0 {
scale_factor
} else {
1.0
};
(delta / (FREYA_PIXEL_SPEED * scale_factor) * PIXEL_SCROLL) as f32
}
pub(crate) fn scroll_pos_from_wheel(wheel: f32, inner: f32, viewport: f32, current: f32) -> i32 {
if viewport >= inner {
return 0;
@ -226,6 +250,8 @@ impl ScrollArea {
let internal = use_scroll_controller(ScrollConfig::default);
let mut controller = self.controller.unwrap_or(internal);
let scale_factor = Platform::get().scale_factor;
let mut viewport_h = use_state(|| 0f32);
let mut viewport_w = use_state(|| 0f32);
let mut viewport_top = use_state(|| 0f32);
@ -310,17 +336,21 @@ impl ScrollArea {
let on_wheel = move |e: Event<WheelEventData>| {
let shift = *shift_held.read();
let scale = *scale_factor.peek();
let delta_x = normalize_wheel_delta(e.delta_x, scale);
let delta_y = normalize_wheel_delta(e.delta_y, scale);
let h_delta = if horizontal {
if shift && e.delta_x == 0.0 {
e.delta_y
if shift && delta_x == 0.0 {
delta_y
} else {
e.delta_x
delta_x
}
} else {
0.0
};
let v_delta = if horizontal && shift { 0.0 } else { e.delta_y };
let v_delta = if horizontal && shift { 0.0 } else { delta_y };
let do_h = h_delta != 0.0 && can_scroll_h;
let do_v = v_delta != 0.0 && can_scroll_v;
@ -337,14 +367,14 @@ impl ScrollArea {
if do_h {
let cur_x = corrected_scroll(content_w, vp_w, *scroll_x.read());
let new_x = scroll_pos_from_wheel(h_delta as f32, content_w, vp_w, cur_x);
let new_x = scroll_pos_from_wheel(h_delta, content_w, vp_w, cur_x);
scroll_x.set(new_x as f32);
}
if do_v {
let (_, cur_y) = controller.into();
let current = corrected_scroll(ct_h, vp_h, cur_y as f32);
let new_y = scroll_pos_from_wheel(v_delta as f32, ct_h, vp_h, current);
let new_y = scroll_pos_from_wheel(v_delta, ct_h, vp_h, current);
if new_y != cur_y {
controller.scroll_to_y(new_y);
}