Fix unscaled scrolling when using an imprecise mouse wheel

This commit is contained in:
Mikayla Maki 2022-11-16 10:44:13 -08:00
parent 3c53fcdb43
commit 8e6c5dbc3b
8 changed files with 83 additions and 28 deletions

View file

@ -192,8 +192,14 @@ impl EditorElement {
.on_scroll({ .on_scroll({
let position_map = position_map.clone(); let position_map = position_map.clone();
move |e, cx| { move |e, cx| {
if !Self::scroll(e.position, e.delta, e.precise, &position_map, bounds, cx) if !Self::scroll(
{ e.position,
*e.delta.raw(),
e.delta.precise(),
&position_map,
bounds,
cx,
) {
cx.propagate_event() cx.propagate_event()
} }
} }

View file

@ -257,17 +257,19 @@ impl Element for Flex {
let axis = self.axis; let axis = self.axis;
move |e, cx| { move |e, cx| {
if remaining_space < 0. { if remaining_space < 0. {
let scroll_delta = e.delta.raw();
let mut delta = match axis { let mut delta = match axis {
Axis::Horizontal => { Axis::Horizontal => {
if e.delta.x().abs() >= e.delta.y().abs() { if scroll_delta.x().abs() >= scroll_delta.y().abs() {
e.delta.x() scroll_delta.x()
} else { } else {
e.delta.y() scroll_delta.y()
} }
} }
Axis::Vertical => e.delta.y(), Axis::Vertical => scroll_delta.y(),
}; };
if !e.precise { if !e.delta.precise() {
delta *= 20.; delta *= 20.;
} }

View file

@ -258,8 +258,8 @@ impl Element for List {
state.0.borrow_mut().scroll( state.0.borrow_mut().scroll(
&scroll_top, &scroll_top,
height, height,
e.platform_event.delta, *e.platform_event.delta.raw(),
e.platform_event.precise, e.platform_event.delta.precise(),
cx, cx,
) )
} }

View file

@ -295,15 +295,19 @@ impl Element for UniformList {
move |MouseScrollWheel { move |MouseScrollWheel {
platform_event: platform_event:
ScrollWheelEvent { ScrollWheelEvent {
position, position, delta, ..
delta,
precise,
..
}, },
.. ..
}, },
cx| { cx| {
if !Self::scroll(state.clone(), position, delta, precise, scroll_max, cx) { if !Self::scroll(
state.clone(),
position,
*delta.raw(),
delta.precise(),
scroll_max,
cx,
) {
cx.propagate_event(); cx.propagate_event();
} }
} }

View file

@ -1,5 +1,7 @@
use std::ops::Deref; use std::ops::Deref;
use pathfinder_geometry::vector::vec2f;
use crate::{geometry::vector::Vector2F, keymap::Keystroke}; use crate::{geometry::vector::Vector2F, keymap::Keystroke};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -44,11 +46,45 @@ pub enum TouchPhase {
Ended, Ended,
} }
#[derive(Clone, Copy, Debug)]
pub enum ScrollDelta {
Pixels(Vector2F),
Lines(Vector2F),
}
impl Default for ScrollDelta {
fn default() -> Self {
Self::Lines(Default::default())
}
}
impl ScrollDelta {
pub fn raw(&self) -> &Vector2F {
match self {
ScrollDelta::Pixels(v) => v,
ScrollDelta::Lines(v) => v,
}
}
pub fn precise(&self) -> bool {
match self {
ScrollDelta::Pixels(_) => true,
ScrollDelta::Lines(_) => false,
}
}
pub fn pixel_delta(&self, line_height: f32) -> Vector2F {
match self {
ScrollDelta::Pixels(delta) => *delta,
ScrollDelta::Lines(delta) => vec2f(delta.x() * line_height, delta.y() * line_height),
}
}
}
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct ScrollWheelEvent { pub struct ScrollWheelEvent {
pub position: Vector2F, pub position: Vector2F,
pub delta: Vector2F, pub delta: ScrollDelta,
pub precise: bool,
pub modifiers: Modifiers, pub modifiers: Modifiers,
/// If the platform supports returning the phase of a scroll wheel event, it will be stored here /// If the platform supports returning the phase of a scroll wheel event, it will be stored here
pub phase: Option<TouchPhase>, pub phase: Option<TouchPhase>,

View file

@ -3,7 +3,7 @@ use crate::{
keymap::Keystroke, keymap::Keystroke,
platform::{Event, NavigationDirection}, platform::{Event, NavigationDirection},
KeyDownEvent, KeyUpEvent, Modifiers, ModifiersChangedEvent, MouseButton, MouseButtonEvent, KeyDownEvent, KeyUpEvent, Modifiers, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
MouseMovedEvent, ScrollWheelEvent, TouchPhase, MouseMovedEvent, ScrollDelta, ScrollWheelEvent, TouchPhase,
}; };
use cocoa::{ use cocoa::{
appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType}, appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType},
@ -164,17 +164,24 @@ impl Event {
_ => Some(TouchPhase::Moved), _ => Some(TouchPhase::Moved),
}; };
let raw_data = vec2f(
native_event.scrollingDeltaX() as f32,
native_event.scrollingDeltaY() as f32,
);
let delta = if native_event.hasPreciseScrollingDeltas() == YES {
ScrollDelta::Pixels(raw_data)
} else {
ScrollDelta::Lines(raw_data)
};
Self::ScrollWheel(ScrollWheelEvent { Self::ScrollWheel(ScrollWheelEvent {
position: vec2f( position: vec2f(
native_event.locationInWindow().x as f32, native_event.locationInWindow().x as f32,
window_height - native_event.locationInWindow().y as f32, window_height - native_event.locationInWindow().y as f32,
), ),
delta: vec2f( delta,
native_event.scrollingDeltaX() as f32,
native_event.scrollingDeltaY() as f32,
),
phase, phase,
precise: native_event.hasPreciseScrollingDeltas() == YES,
modifiers: read_modifiers(native_event), modifiers: read_modifiers(native_event),
}) })
}), }),

View file

@ -97,7 +97,7 @@ impl MouseButton {
} }
fn from_scroll(e: &ScrollWheelEvent) -> Self { fn from_scroll(e: &ScrollWheelEvent) -> Self {
if e.delta.y() > 0. { if e.delta.raw().y() > 0. {
MouseButton::ScrollUp MouseButton::ScrollUp
} else { } else {
MouseButton::ScrollDown MouseButton::ScrollDown

View file

@ -1144,7 +1144,7 @@ impl Terminal {
fn determine_scroll_lines(&mut self, e: &MouseScrollWheel, mouse_mode: bool) -> Option<i32> { fn determine_scroll_lines(&mut self, e: &MouseScrollWheel, mouse_mode: bool) -> Option<i32> {
let scroll_multiplier = if mouse_mode { 1. } else { SCROLL_MULTIPLIER }; let scroll_multiplier = if mouse_mode { 1. } else { SCROLL_MULTIPLIER };
let line_height = self.last_content.size.line_height;
match e.phase { match e.phase {
/* Reset scroll state on started */ /* Reset scroll state on started */
Some(gpui::TouchPhase::Started) => { Some(gpui::TouchPhase::Started) => {
@ -1153,11 +1153,11 @@ impl Terminal {
} }
/* Calculate the appropriate scroll lines */ /* Calculate the appropriate scroll lines */
Some(gpui::TouchPhase::Moved) => { Some(gpui::TouchPhase::Moved) => {
let old_offset = (self.scroll_px / self.last_content.size.line_height) as i32; let old_offset = (self.scroll_px / line_height) as i32;
self.scroll_px += e.delta.y() * scroll_multiplier; self.scroll_px += e.delta.pixel_delta(line_height).y() * scroll_multiplier;
let new_offset = (self.scroll_px / self.last_content.size.line_height) as i32; let new_offset = (self.scroll_px / line_height) as i32;
// Whenever we hit the edges, reset our stored scroll to 0 // Whenever we hit the edges, reset our stored scroll to 0
// so we can respond to changes in direction quickly // so we can respond to changes in direction quickly
@ -1167,7 +1167,7 @@ impl Terminal {
} }
/* Fall back to delta / line_height */ /* Fall back to delta / line_height */
None => Some( None => Some(
((e.delta.y() * scroll_multiplier) / self.last_content.size.line_height) as i32, ((e.delta.pixel_delta(line_height).y() * scroll_multiplier) / line_height) as i32,
), ),
_ => None, _ => None,
} }