mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Lock trackpad scrolling in buffers to axis until broken free
This commit is contained in:
parent
79cf5dbd4b
commit
cbc15b6b58
2 changed files with 96 additions and 11 deletions
|
@ -35,9 +35,9 @@ use gpui::{
|
|||
impl_actions, impl_internal_actions,
|
||||
platform::CursorStyle,
|
||||
serde_json::json,
|
||||
text_layout, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox,
|
||||
Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View,
|
||||
ViewContext, ViewHandle, WeakViewHandle,
|
||||
text_layout, AnyViewHandle, AppContext, AsyncAppContext, Axis, ClipboardItem, Element,
|
||||
ElementBox, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription,
|
||||
Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||
};
|
||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||
use hover_popover::{hide_hover, HoverState};
|
||||
|
@ -84,6 +84,7 @@ const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
|
|||
const MAX_LINE_LEN: usize = 1024;
|
||||
const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
|
||||
const MAX_SELECTION_HISTORY_LEN: usize = 1024;
|
||||
pub const SCROLL_EVENT_SEPARATION: Duration = Duration::from_millis(28);
|
||||
|
||||
pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
|
||||
|
||||
|
@ -94,7 +95,10 @@ pub struct SelectNext {
|
|||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Scroll(pub Vector2F);
|
||||
pub struct Scroll {
|
||||
pub scroll_position: Vector2F,
|
||||
pub axis: Option<Axis>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Select(pub SelectPhase);
|
||||
|
@ -263,7 +267,7 @@ struct ScrollbarAutoHide(bool);
|
|||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(Editor::new_file);
|
||||
cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
|
||||
cx.add_action(Editor::scroll);
|
||||
cx.add_action(Editor::select);
|
||||
cx.add_action(Editor::cancel);
|
||||
cx.add_action(Editor::newline);
|
||||
|
@ -429,6 +433,69 @@ pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor;
|
|||
|
||||
type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OngoingScroll {
|
||||
last_timestamp: Instant,
|
||||
axis: Option<Axis>,
|
||||
}
|
||||
|
||||
impl OngoingScroll {
|
||||
fn initial() -> OngoingScroll {
|
||||
OngoingScroll {
|
||||
last_timestamp: Instant::now() - SCROLL_EVENT_SEPARATION,
|
||||
axis: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, axis: Option<Axis>) {
|
||||
self.last_timestamp = Instant::now();
|
||||
self.axis = axis;
|
||||
}
|
||||
|
||||
pub fn filter(&self, delta: &mut Vector2F) -> Option<Axis> {
|
||||
const UNLOCK_PERCENT: f32 = 1.9;
|
||||
const UNLOCK_LOWER_BOUND: f32 = 6.;
|
||||
let mut axis = self.axis;
|
||||
|
||||
let x = delta.x().abs();
|
||||
let y = delta.y().abs();
|
||||
let duration = Instant::now().duration_since(self.last_timestamp);
|
||||
if duration > SCROLL_EVENT_SEPARATION {
|
||||
//New ongoing scroll will start, determine axis
|
||||
axis = if x <= y {
|
||||
Some(Axis::Vertical)
|
||||
} else {
|
||||
Some(Axis::Horizontal)
|
||||
};
|
||||
} else if x.max(y) >= UNLOCK_LOWER_BOUND {
|
||||
//Check if the current ongoing will need to unlock
|
||||
match axis {
|
||||
Some(Axis::Vertical) => {
|
||||
if x > y && x >= y * UNLOCK_PERCENT {
|
||||
axis = None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(Axis::Horizontal) => {
|
||||
if y > x && y >= x * UNLOCK_PERCENT {
|
||||
axis = None;
|
||||
}
|
||||
}
|
||||
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
match axis {
|
||||
Some(Axis::Vertical) => *delta = vec2f(0., delta.y()),
|
||||
Some(Axis::Horizontal) => *delta = vec2f(delta.x(), 0.),
|
||||
None => {}
|
||||
}
|
||||
|
||||
axis
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Editor {
|
||||
handle: WeakViewHandle<Self>,
|
||||
buffer: ModelHandle<MultiBuffer>,
|
||||
|
@ -443,6 +510,7 @@ pub struct Editor {
|
|||
select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
|
||||
ime_transaction: Option<TransactionId>,
|
||||
active_diagnostics: Option<ActiveDiagnosticGroup>,
|
||||
ongoing_scroll: OngoingScroll,
|
||||
scroll_position: Vector2F,
|
||||
scroll_top_anchor: Anchor,
|
||||
autoscroll_request: Option<(Autoscroll, bool)>,
|
||||
|
@ -486,6 +554,7 @@ pub struct EditorSnapshot {
|
|||
pub display_snapshot: DisplaySnapshot,
|
||||
pub placeholder_text: Option<Arc<str>>,
|
||||
is_focused: bool,
|
||||
ongoing_scroll: OngoingScroll,
|
||||
scroll_position: Vector2F,
|
||||
scroll_top_anchor: Anchor,
|
||||
}
|
||||
|
@ -1097,6 +1166,7 @@ impl Editor {
|
|||
soft_wrap_mode_override: None,
|
||||
get_field_editor_theme,
|
||||
project,
|
||||
ongoing_scroll: OngoingScroll::initial(),
|
||||
scroll_position: Vector2F::zero(),
|
||||
scroll_top_anchor: Anchor::min(),
|
||||
autoscroll_request: None,
|
||||
|
@ -1189,6 +1259,7 @@ impl Editor {
|
|||
EditorSnapshot {
|
||||
mode: self.mode,
|
||||
display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
|
||||
ongoing_scroll: self.ongoing_scroll,
|
||||
scroll_position: self.scroll_position,
|
||||
scroll_top_anchor: self.scroll_top_anchor.clone(),
|
||||
placeholder_text: self.placeholder_text.clone(),
|
||||
|
@ -1592,6 +1663,11 @@ impl Editor {
|
|||
});
|
||||
}
|
||||
|
||||
fn scroll(&mut self, action: &Scroll, cx: &mut ViewContext<Self>) {
|
||||
self.ongoing_scroll.update(action.axis);
|
||||
self.set_scroll_position(action.scroll_position, cx);
|
||||
}
|
||||
|
||||
fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
|
||||
self.hide_context_menu(cx);
|
||||
|
||||
|
|
|
@ -423,18 +423,27 @@ impl EditorElement {
|
|||
return false;
|
||||
}
|
||||
|
||||
let line_height = position_map.line_height;
|
||||
let max_glyph_width = position_map.em_width;
|
||||
if !precise {
|
||||
delta *= vec2f(max_glyph_width, position_map.line_height);
|
||||
}
|
||||
|
||||
let axis = if precise {
|
||||
//Trackpad
|
||||
position_map.snapshot.ongoing_scroll.filter(&mut delta)
|
||||
} else {
|
||||
//Not trackpad
|
||||
delta *= vec2f(max_glyph_width, line_height);
|
||||
None //Resets ongoing scroll
|
||||
};
|
||||
|
||||
let scroll_position = position_map.snapshot.scroll_position();
|
||||
let x = (scroll_position.x() * max_glyph_width - delta.x()) / max_glyph_width;
|
||||
let y =
|
||||
(scroll_position.y() * position_map.line_height - delta.y()) / position_map.line_height;
|
||||
let y = (scroll_position.y() * line_height - delta.y()) / line_height;
|
||||
let scroll_position = vec2f(x, y).clamp(Vector2F::zero(), position_map.scroll_max);
|
||||
|
||||
cx.dispatch_action(Scroll(scroll_position));
|
||||
cx.dispatch_action(Scroll {
|
||||
scroll_position,
|
||||
axis,
|
||||
});
|
||||
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue