mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-11 13:10:54 +00:00
Merge branch 'terminal-scrolling-sensitivity' into terminal-polishing
This commit is contained in:
commit
d189972a0d
3 changed files with 81 additions and 37 deletions
|
@ -19,6 +19,15 @@ pub struct ModifiersChangedEvent {
|
||||||
pub cmd: bool,
|
pub cmd: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The phase of a touch motion event.
|
||||||
|
/// Based on the winit enum of the same name,
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum TouchPhase {
|
||||||
|
Started,
|
||||||
|
Moved,
|
||||||
|
Ended,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct ScrollWheelEvent {
|
pub struct ScrollWheelEvent {
|
||||||
pub position: Vector2F,
|
pub position: Vector2F,
|
||||||
|
@ -28,6 +37,8 @@ pub struct ScrollWheelEvent {
|
||||||
pub alt: bool,
|
pub alt: bool,
|
||||||
pub shift: bool,
|
pub shift: bool,
|
||||||
pub cmd: bool,
|
pub cmd: bool,
|
||||||
|
/// If the platform supports returning the phase of a scroll wheel event, it will be stored here
|
||||||
|
pub phase: Option<TouchPhase>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
|
|
|
@ -3,10 +3,10 @@ use crate::{
|
||||||
keymap::Keystroke,
|
keymap::Keystroke,
|
||||||
platform::{Event, NavigationDirection},
|
platform::{Event, NavigationDirection},
|
||||||
KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
|
KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
|
||||||
MouseMovedEvent, ScrollWheelEvent,
|
MouseMovedEvent, ScrollWheelEvent, TouchPhase,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSEvent, NSEventModifierFlags, NSEventType},
|
appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType},
|
||||||
base::{id, YES},
|
base::{id, YES},
|
||||||
foundation::NSString as _,
|
foundation::NSString as _,
|
||||||
};
|
};
|
||||||
|
@ -150,6 +150,14 @@ impl Event {
|
||||||
NSEventType::NSScrollWheel => window_height.map(|window_height| {
|
NSEventType::NSScrollWheel => window_height.map(|window_height| {
|
||||||
let modifiers = native_event.modifierFlags();
|
let modifiers = native_event.modifierFlags();
|
||||||
|
|
||||||
|
let phase = match native_event.phase() {
|
||||||
|
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
|
||||||
|
Some(TouchPhase::Started)
|
||||||
|
}
|
||||||
|
NSEventPhase::NSEventPhaseEnded => Some(TouchPhase::Ended),
|
||||||
|
_ => Some(TouchPhase::Moved),
|
||||||
|
};
|
||||||
|
|
||||||
Self::ScrollWheel(ScrollWheelEvent {
|
Self::ScrollWheel(ScrollWheelEvent {
|
||||||
position: vec2f(
|
position: vec2f(
|
||||||
native_event.locationInWindow().x as f32,
|
native_event.locationInWindow().x as f32,
|
||||||
|
@ -159,6 +167,7 @@ impl Event {
|
||||||
native_event.scrollingDeltaX() as f32,
|
native_event.scrollingDeltaX() as f32,
|
||||||
native_event.scrollingDeltaY() as f32,
|
native_event.scrollingDeltaY() as f32,
|
||||||
),
|
),
|
||||||
|
phase,
|
||||||
precise: native_event.hasPreciseScrollingDeltas() == YES,
|
precise: native_event.hasPreciseScrollingDeltas() == YES,
|
||||||
ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
|
ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
|
||||||
alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
|
alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
|
||||||
|
|
|
@ -72,7 +72,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
||||||
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
||||||
///Implement scroll bars.
|
///Implement scroll bars.
|
||||||
const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
|
const SCROLL_MULTIPLIER: f32 = 4.;
|
||||||
const MAX_SEARCH_LINES: usize = 100;
|
const MAX_SEARCH_LINES: usize = 100;
|
||||||
const DEBUG_TERMINAL_WIDTH: f32 = 500.;
|
const DEBUG_TERMINAL_WIDTH: f32 = 500.;
|
||||||
const DEBUG_TERMINAL_HEIGHT: f32 = 30.;
|
const DEBUG_TERMINAL_HEIGHT: f32 = 30.;
|
||||||
|
@ -381,6 +381,7 @@ impl TerminalBuilder {
|
||||||
shell_pid,
|
shell_pid,
|
||||||
foreground_process_info: None,
|
foreground_process_info: None,
|
||||||
breadcrumb_text: String::new(),
|
breadcrumb_text: String::new(),
|
||||||
|
scroll_px: 0.,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TerminalBuilder {
|
Ok(TerminalBuilder {
|
||||||
|
@ -500,6 +501,7 @@ pub struct Terminal {
|
||||||
shell_pid: u32,
|
shell_pid: u32,
|
||||||
shell_fd: u32,
|
shell_fd: u32,
|
||||||
foreground_process_info: Option<LocalProcessInfo>,
|
foreground_process_info: Option<LocalProcessInfo>,
|
||||||
|
scroll_px: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terminal {
|
impl Terminal {
|
||||||
|
@ -893,47 +895,69 @@ impl Terminal {
|
||||||
|
|
||||||
///Scroll the terminal
|
///Scroll the terminal
|
||||||
pub fn scroll_wheel(&mut self, e: &ScrollWheelEvent, origin: Vector2F) {
|
pub fn scroll_wheel(&mut self, e: &ScrollWheelEvent, origin: Vector2F) {
|
||||||
if self.mouse_mode(e.shift) {
|
let mouse_mode = self.mouse_mode(e.shift);
|
||||||
//TODO: Currently this only sends the current scroll reports as they come in. Alacritty
|
|
||||||
//Sends the *entire* scroll delta on *every* scroll event, only resetting it when
|
|
||||||
//The scroll enters 'TouchPhase::Started'. Do I need to replicate this?
|
|
||||||
//This would be consistent with a scroll model based on 'distance from origin'...
|
|
||||||
let scroll_lines = (e.delta.y() / self.cur_size.line_height) as i32;
|
|
||||||
let point = mouse_point(
|
|
||||||
e.position.sub(origin),
|
|
||||||
self.cur_size,
|
|
||||||
self.last_content.display_offset,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(scrolls) =
|
if let Some(scroll_lines) = self.determine_scroll_lines(e, mouse_mode) {
|
||||||
scroll_report(point, scroll_lines as i32, e, self.last_content.mode)
|
if mouse_mode {
|
||||||
|
let point = mouse_point(
|
||||||
|
e.position.sub(origin),
|
||||||
|
self.cur_size,
|
||||||
|
self.last_content.display_offset,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(scrolls) =
|
||||||
|
scroll_report(point, scroll_lines as i32, e, self.last_content.mode)
|
||||||
|
{
|
||||||
|
for scroll in scrolls {
|
||||||
|
self.pty_tx.notify(scroll);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if self
|
||||||
|
.last_content
|
||||||
|
.mode
|
||||||
|
.contains(TermMode::ALT_SCREEN | TermMode::ALTERNATE_SCROLL)
|
||||||
|
&& !e.shift
|
||||||
{
|
{
|
||||||
for scroll in scrolls {
|
self.pty_tx.notify(alt_scroll(scroll_lines))
|
||||||
self.pty_tx.notify(scroll);
|
} else {
|
||||||
|
if scroll_lines != 0 {
|
||||||
|
let scroll = AlacScroll::Delta(scroll_lines);
|
||||||
|
|
||||||
|
self.events.push_back(InternalEvent::Scroll(scroll));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
} else if self
|
|
||||||
.last_content
|
|
||||||
.mode
|
|
||||||
.contains(TermMode::ALT_SCREEN | TermMode::ALTERNATE_SCROLL)
|
|
||||||
&& !e.shift
|
|
||||||
{
|
|
||||||
//TODO: See above TODO, also applies here.
|
|
||||||
let scroll_lines =
|
|
||||||
((e.delta.y() * ALACRITTY_SCROLL_MULTIPLIER) / self.cur_size.line_height) as i32;
|
|
||||||
|
|
||||||
self.pty_tx.notify(alt_scroll(scroll_lines))
|
|
||||||
} else {
|
|
||||||
let scroll_lines =
|
|
||||||
((e.delta.y() * ALACRITTY_SCROLL_MULTIPLIER) / self.cur_size.line_height) as i32;
|
|
||||||
if scroll_lines != 0 {
|
|
||||||
let scroll = AlacScroll::Delta(scroll_lines);
|
|
||||||
|
|
||||||
self.events.push_back(InternalEvent::Scroll(scroll));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn determine_scroll_lines(&mut self, e: &ScrollWheelEvent, mouse_mode: bool) -> Option<i32> {
|
||||||
|
let scroll_multiplier = if mouse_mode { 1. } else { SCROLL_MULTIPLIER };
|
||||||
|
|
||||||
|
match e.phase {
|
||||||
|
/* Reset scroll state on started */
|
||||||
|
Some(gpui::TouchPhase::Started) => {
|
||||||
|
self.scroll_px = 0.;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
/* Calculate the appropriate scroll lines */
|
||||||
|
Some(gpui::TouchPhase::Moved) => {
|
||||||
|
let old_offset = (self.scroll_px / self.cur_size.line_height) as i32;
|
||||||
|
|
||||||
|
self.scroll_px += e.delta.y() * scroll_multiplier;
|
||||||
|
|
||||||
|
let new_offset = (self.scroll_px / self.cur_size.line_height) as i32;
|
||||||
|
|
||||||
|
// Whenever we hit the edges, reset our stored scroll to 0
|
||||||
|
// so we can respond to changes in direction quickly
|
||||||
|
self.scroll_px %= self.cur_size.height;
|
||||||
|
|
||||||
|
Some(new_offset - old_offset)
|
||||||
|
}
|
||||||
|
/* Fall back to delta / line_height */
|
||||||
|
None => Some(((e.delta.y() * scroll_multiplier) / self.cur_size.line_height) as i32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_matches(
|
pub fn find_matches(
|
||||||
&mut self,
|
&mut self,
|
||||||
query: project::search::SearchQuery,
|
query: project::search::SearchQuery,
|
||||||
|
|
Loading…
Reference in a new issue