Fix unscaled scrolling when using an imprecise mouse wheel
This commit is contained in:
parent
3c53fcdb43
commit
8e6c5dbc3b
8 changed files with 83 additions and 28 deletions
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue