diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 7c89eacde8..774d8fbc9e 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -472,6 +472,15 @@ "terminal::SendText", "\u0001" ], + // Terminal.app compatability + "alt-left": [ + "terminal::SendText", + "\u001bb" + ], + "alt-right": [ + "terminal::SendText", + "\u001bf" + ], // There are conflicting bindings for these keys in the global context. // these bindings override them, remove at your own risk: "up": [ diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 25100037d7..f62f27bb0d 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -192,8 +192,14 @@ impl EditorElement { .on_scroll({ let position_map = position_map.clone(); 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() } } diff --git a/crates/gpui/src/elements/flex.rs b/crates/gpui/src/elements/flex.rs index 129d36dadd..f6a1a5d8e6 100644 --- a/crates/gpui/src/elements/flex.rs +++ b/crates/gpui/src/elements/flex.rs @@ -257,17 +257,19 @@ impl Element for Flex { let axis = self.axis; move |e, cx| { if remaining_space < 0. { + let scroll_delta = e.delta.raw(); + let mut delta = match axis { Axis::Horizontal => { - if e.delta.x().abs() >= e.delta.y().abs() { - e.delta.x() + if scroll_delta.x().abs() >= scroll_delta.y().abs() { + scroll_delta.x() } 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.; } diff --git a/crates/gpui/src/elements/list.rs b/crates/gpui/src/elements/list.rs index f1b747d647..53a0b70b35 100644 --- a/crates/gpui/src/elements/list.rs +++ b/crates/gpui/src/elements/list.rs @@ -258,8 +258,8 @@ impl Element for List { state.0.borrow_mut().scroll( &scroll_top, height, - e.platform_event.delta, - e.platform_event.precise, + *e.platform_event.delta.raw(), + e.platform_event.delta.precise(), cx, ) } diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index 0eab7f0bc9..79836b70e8 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -295,15 +295,19 @@ impl Element for UniformList { move |MouseScrollWheel { platform_event: ScrollWheelEvent { - position, - delta, - precise, - .. + position, delta, .. }, .. }, 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(); } } diff --git a/crates/gpui/src/platform/event.rs b/crates/gpui/src/platform/event.rs index a309f5123f..862807a74d 100644 --- a/crates/gpui/src/platform/event.rs +++ b/crates/gpui/src/platform/event.rs @@ -1,5 +1,7 @@ use std::ops::Deref; +use pathfinder_geometry::vector::vec2f; + use crate::{geometry::vector::Vector2F, keymap::Keystroke}; #[derive(Clone, Debug)] @@ -44,11 +46,45 @@ pub enum TouchPhase { 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)] pub struct ScrollWheelEvent { pub position: Vector2F, - pub delta: Vector2F, - pub precise: bool, + pub delta: ScrollDelta, pub modifiers: Modifiers, /// If the platform supports returning the phase of a scroll wheel event, it will be stored here pub phase: Option, diff --git a/crates/gpui/src/platform/mac/event.rs b/crates/gpui/src/platform/mac/event.rs index 77d1e67cae..36dab73149 100644 --- a/crates/gpui/src/platform/mac/event.rs +++ b/crates/gpui/src/platform/mac/event.rs @@ -3,7 +3,7 @@ use crate::{ keymap::Keystroke, platform::{Event, NavigationDirection}, KeyDownEvent, KeyUpEvent, Modifiers, ModifiersChangedEvent, MouseButton, MouseButtonEvent, - MouseMovedEvent, ScrollWheelEvent, TouchPhase, + MouseMovedEvent, ScrollDelta, ScrollWheelEvent, TouchPhase, }; use cocoa::{ appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType}, @@ -164,17 +164,24 @@ impl Event { _ => 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 { position: vec2f( native_event.locationInWindow().x as f32, window_height - native_event.locationInWindow().y as f32, ), - delta: vec2f( - native_event.scrollingDeltaX() as f32, - native_event.scrollingDeltaY() as f32, - ), + delta, phase, - precise: native_event.hasPreciseScrollingDeltas() == YES, modifiers: read_modifiers(native_event), }) }), diff --git a/crates/terminal/src/mappings/keys.rs b/crates/terminal/src/mappings/keys.rs index 199f42df65..ddcd6c5898 100644 --- a/crates/terminal/src/mappings/keys.rs +++ b/crates/terminal/src/mappings/keys.rs @@ -36,18 +36,6 @@ impl Modifiers { } } -///This function checks if to_esc_str would work, assuming all terminal settings are off. -///Note that this function is conservative. It can fail in cases where the actual to_esc_str succeeds. -///This is unavoidable for our use case. GPUI cannot wait until we acquire the terminal -///lock to determine whether we could actually send the keystroke with the current settings. Therefore, -///This conservative guess is used instead. Note that in practice the case where this method -///Returns false when the actual terminal would consume the keystroke never happens. All keystrokes -///that depend on terminal modes also have a mapping that doesn't depend on the terminal mode. -///This is fragile, but as these mappings are locked up in legacy compatibility, it's probably good enough -pub fn might_convert(keystroke: &Keystroke) -> bool { - to_esc_str(keystroke, &TermMode::NONE, false).is_some() -} - pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) -> Option { let modifiers = Modifiers::new(keystroke); diff --git a/crates/terminal/src/mappings/mouse.rs b/crates/terminal/src/mappings/mouse.rs index 2254eea5af..4dd97aa4c6 100644 --- a/crates/terminal/src/mappings/mouse.rs +++ b/crates/terminal/src/mappings/mouse.rs @@ -97,7 +97,7 @@ impl MouseButton { } fn from_scroll(e: &ScrollWheelEvent) -> Self { - if e.delta.y() > 0. { + if e.delta.raw().y() > 0. { MouseButton::ScrollUp } else { MouseButton::ScrollDown diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 761dad6675..8b5b20e81e 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -635,7 +635,7 @@ impl Terminal { term.grid_mut().reset_region(..cursor.line); // Copy the current line up - let line = term.grid()[cursor.line][..cursor.column] + let line = term.grid()[cursor.line][..Column(term.grid().columns())] .iter() .cloned() .enumerate() @@ -1144,7 +1144,7 @@ impl Terminal { fn determine_scroll_lines(&mut self, e: &MouseScrollWheel, mouse_mode: bool) -> Option { let scroll_multiplier = if mouse_mode { 1. } else { SCROLL_MULTIPLIER }; - + let line_height = self.last_content.size.line_height; match e.phase { /* Reset scroll state on started */ Some(gpui::TouchPhase::Started) => { @@ -1153,11 +1153,11 @@ impl Terminal { } /* Calculate the appropriate scroll lines */ 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 // so we can respond to changes in direction quickly @@ -1167,7 +1167,7 @@ impl Terminal { } /* Fall back to delta / line_height */ 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, }