Terminal mouse improvements (#25104)
Closes #24911 Closes #17983 Closes #7073 Release Notes: - Terminal: Fix cmd-click on links/files when terminal is not focused - Terminal: Remove hover treatment after Zed hides/re-opens --------- Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This commit is contained in:
parent
b1872e3afd
commit
60a44359e4
6 changed files with 229 additions and 230 deletions
|
@ -21,7 +21,7 @@ use terminal::{
|
|||
},
|
||||
},
|
||||
terminal_settings::TerminalSettings,
|
||||
HoveredWord, IndexedCell, Terminal, TerminalContent, TerminalSize,
|
||||
HoveredWord, IndexedCell, Terminal, TerminalBounds, TerminalContent,
|
||||
};
|
||||
use theme::{ActiveTheme, Theme, ThemeSettings};
|
||||
use ui::{ParentElement, Tooltip};
|
||||
|
@ -40,7 +40,7 @@ pub struct LayoutState {
|
|||
relative_highlighted_ranges: Vec<(RangeInclusive<AlacPoint>, Hsla)>,
|
||||
cursor: Option<CursorLayout>,
|
||||
background_color: Hsla,
|
||||
dimensions: TerminalSize,
|
||||
dimensions: TerminalBounds,
|
||||
mode: TermMode,
|
||||
display_offset: usize,
|
||||
hyperlink_tooltip: Option<AnyElement>,
|
||||
|
@ -86,7 +86,7 @@ impl LayoutCell {
|
|||
pub fn paint(
|
||||
&self,
|
||||
origin: Point<Pixels>,
|
||||
dimensions: &TerminalSize,
|
||||
dimensions: &TerminalBounds,
|
||||
_visible_bounds: Bounds<Pixels>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
|
@ -130,7 +130,7 @@ impl LayoutRect {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn paint(&self, origin: Point<Pixels>, dimensions: &TerminalSize, window: &mut Window) {
|
||||
pub fn paint(&self, origin: Point<Pixels>, dimensions: &TerminalBounds, window: &mut Window) {
|
||||
let position = {
|
||||
let alac_point = self.point;
|
||||
point(
|
||||
|
@ -313,7 +313,7 @@ impl TerminalElement {
|
|||
/// the same position for sequential indexes. Use em_width instead
|
||||
fn shape_cursor(
|
||||
cursor_point: DisplayCursor,
|
||||
size: TerminalSize,
|
||||
size: TerminalBounds,
|
||||
text_fragment: &ShapedLine,
|
||||
) -> Option<(Point<Pixels>, Pixels)> {
|
||||
if cursor_point.line() < size.total_lines() as i32 {
|
||||
|
@ -412,27 +412,20 @@ impl TerminalElement {
|
|||
|
||||
fn generic_button_handler<E>(
|
||||
connection: Entity<Terminal>,
|
||||
origin: Point<Pixels>,
|
||||
focus_handle: FocusHandle,
|
||||
f: impl Fn(&mut Terminal, Point<Pixels>, &E, &mut Context<Terminal>),
|
||||
f: impl Fn(&mut Terminal, &E, &mut Context<Terminal>),
|
||||
) -> impl Fn(&E, &mut Window, &mut App) {
|
||||
move |event, window, cx| {
|
||||
window.focus(&focus_handle);
|
||||
connection.update(cx, |terminal, cx| {
|
||||
f(terminal, origin, event, cx);
|
||||
f(terminal, event, cx);
|
||||
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn register_mouse_listeners(
|
||||
&mut self,
|
||||
origin: Point<Pixels>,
|
||||
mode: TermMode,
|
||||
hitbox: &Hitbox,
|
||||
window: &mut Window,
|
||||
) {
|
||||
fn register_mouse_listeners(&mut self, mode: TermMode, hitbox: &Hitbox, window: &mut Window) {
|
||||
let focus = self.focus.clone();
|
||||
let terminal = self.terminal.clone();
|
||||
|
||||
|
@ -442,29 +435,26 @@ impl TerminalElement {
|
|||
move |e, window, cx| {
|
||||
window.focus(&focus);
|
||||
terminal.update(cx, |terminal, cx| {
|
||||
terminal.mouse_down(e, origin, cx);
|
||||
terminal.mouse_down(e, cx);
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
window.on_mouse_event({
|
||||
let focus = self.focus.clone();
|
||||
let terminal = self.terminal.clone();
|
||||
let hitbox = hitbox.clone();
|
||||
let focus = focus.clone();
|
||||
move |e: &MouseMoveEvent, phase, window, cx| {
|
||||
if phase != DispatchPhase::Bubble || !focus.is_focused(window) {
|
||||
if phase != DispatchPhase::Bubble {
|
||||
return;
|
||||
}
|
||||
|
||||
if e.pressed_button.is_some() && !cx.has_active_drag() {
|
||||
if e.pressed_button.is_some() && !cx.has_active_drag() && focus.is_focused(window) {
|
||||
let hovered = hitbox.is_hovered(window);
|
||||
terminal.update(cx, |terminal, cx| {
|
||||
if terminal.selection_started() {
|
||||
terminal.mouse_drag(e, origin, hitbox.bounds);
|
||||
cx.notify();
|
||||
} else if hovered {
|
||||
terminal.mouse_drag(e, origin, hitbox.bounds);
|
||||
if terminal.selection_started() || hovered {
|
||||
terminal.mouse_drag(e, hitbox.bounds, cx);
|
||||
cx.notify();
|
||||
}
|
||||
})
|
||||
|
@ -472,8 +462,7 @@ impl TerminalElement {
|
|||
|
||||
if hitbox.is_hovered(window) {
|
||||
terminal.update(cx, |terminal, cx| {
|
||||
terminal.mouse_move(e, origin);
|
||||
cx.notify();
|
||||
terminal.mouse_move(e, cx);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -483,10 +472,9 @@ impl TerminalElement {
|
|||
MouseButton::Left,
|
||||
TerminalElement::generic_button_handler(
|
||||
terminal.clone(),
|
||||
origin,
|
||||
focus.clone(),
|
||||
move |terminal, origin, e, cx| {
|
||||
terminal.mouse_up(e, origin, cx);
|
||||
move |terminal, e, cx| {
|
||||
terminal.mouse_up(e, cx);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -494,10 +482,9 @@ impl TerminalElement {
|
|||
MouseButton::Middle,
|
||||
TerminalElement::generic_button_handler(
|
||||
terminal.clone(),
|
||||
origin,
|
||||
focus.clone(),
|
||||
move |terminal, origin, e, cx| {
|
||||
terminal.mouse_down(e, origin, cx);
|
||||
move |terminal, e, cx| {
|
||||
terminal.mouse_down(e, cx);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -506,7 +493,7 @@ impl TerminalElement {
|
|||
move |e, _, cx| {
|
||||
terminal_view
|
||||
.update(cx, |terminal_view, cx| {
|
||||
terminal_view.scroll_wheel(e, origin, cx);
|
||||
terminal_view.scroll_wheel(e, cx);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
|
@ -520,10 +507,9 @@ impl TerminalElement {
|
|||
MouseButton::Right,
|
||||
TerminalElement::generic_button_handler(
|
||||
terminal.clone(),
|
||||
origin,
|
||||
focus.clone(),
|
||||
move |terminal, origin, e, cx| {
|
||||
terminal.mouse_down(e, origin, cx);
|
||||
move |terminal, e, cx| {
|
||||
terminal.mouse_down(e, cx);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -531,23 +517,17 @@ impl TerminalElement {
|
|||
MouseButton::Right,
|
||||
TerminalElement::generic_button_handler(
|
||||
terminal.clone(),
|
||||
origin,
|
||||
focus.clone(),
|
||||
move |terminal, origin, e, cx| {
|
||||
terminal.mouse_up(e, origin, cx);
|
||||
move |terminal, e, cx| {
|
||||
terminal.mouse_up(e, cx);
|
||||
},
|
||||
),
|
||||
);
|
||||
self.interactivity.on_mouse_up(
|
||||
MouseButton::Middle,
|
||||
TerminalElement::generic_button_handler(
|
||||
terminal,
|
||||
origin,
|
||||
focus,
|
||||
move |terminal, origin, e, cx| {
|
||||
terminal.mouse_up(e, origin, cx);
|
||||
},
|
||||
),
|
||||
TerminalElement::generic_button_handler(terminal, focus, move |terminal, e, cx| {
|
||||
terminal.mouse_up(e, cx);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -705,7 +685,10 @@ impl Element for TerminalElement {
|
|||
size.width = cell_width * 2.0;
|
||||
}
|
||||
|
||||
TerminalSize::new(line_height, cell_width, size)
|
||||
let mut origin = bounds.origin;
|
||||
origin.x += gutter;
|
||||
|
||||
TerminalBounds::new(line_height, cell_width, Bounds { origin, size })
|
||||
};
|
||||
|
||||
let search_matches = self.terminal.read(cx).matches.clone();
|
||||
|
@ -714,9 +697,11 @@ impl Element for TerminalElement {
|
|||
|
||||
let last_hovered_word = self.terminal.update(cx, |terminal, cx| {
|
||||
terminal.set_size(dimensions);
|
||||
terminal.sync(cx);
|
||||
terminal.sync(window, cx);
|
||||
|
||||
if self.can_navigate_to_selected_word
|
||||
&& terminal.can_navigate_to_selected_word()
|
||||
&& window.modifiers().secondary()
|
||||
&& bounds.contains(&window.mouse_position())
|
||||
{
|
||||
terminal.last_content.last_hovered_word.clone()
|
||||
} else {
|
||||
|
@ -898,7 +883,7 @@ impl Element for TerminalElement {
|
|||
workspace: self.workspace.clone(),
|
||||
};
|
||||
|
||||
self.register_mouse_listeners(origin, layout.mode, &layout.hitbox, window);
|
||||
self.register_mouse_listeners(layout.mode, &layout.hitbox, window);
|
||||
if self.can_navigate_to_selected_word && layout.last_hovered_word.is_some() {
|
||||
window.set_cursor_style(gpui::CursorStyle::PointingHand, &layout.hitbox);
|
||||
} else {
|
||||
|
@ -924,12 +909,9 @@ impl Element for TerminalElement {
|
|||
return;
|
||||
}
|
||||
|
||||
let handled = this
|
||||
.update(cx, |term, _| term.try_modifiers_change(&event.modifiers));
|
||||
|
||||
if handled {
|
||||
window.refresh();
|
||||
}
|
||||
this.update(cx, |term, cx| {
|
||||
term.try_modifiers_change(&event.modifiers, window, cx)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ struct ScrollHandleState {
|
|||
impl ScrollHandleState {
|
||||
fn new(terminal: &Terminal) -> Self {
|
||||
Self {
|
||||
line_height: terminal.last_content().size.line_height,
|
||||
line_height: terminal.last_content().terminal_bounds.line_height,
|
||||
total_lines: terminal.total_lines(),
|
||||
viewport_lines: terminal.viewport_lines(),
|
||||
display_offset: terminal.last_content().display_offset,
|
||||
|
|
|
@ -23,7 +23,7 @@ use terminal::{
|
|||
terminal_settings::{self, CursorShape, TerminalBlink, TerminalSettings, WorkingDirectory},
|
||||
Clear, Copy, Event, MaybeNavigationTarget, Paste, ScrollLineDown, ScrollLineUp, ScrollPageDown,
|
||||
ScrollPageUp, ScrollToBottom, ScrollToTop, ShowCharacterPalette, TaskStatus, Terminal,
|
||||
TerminalSize, ToggleViMode,
|
||||
TerminalBounds, ToggleViMode,
|
||||
};
|
||||
use terminal_element::{is_blank, TerminalElement};
|
||||
use terminal_panel::TerminalPanel;
|
||||
|
@ -101,7 +101,7 @@ pub struct BlockProperties {
|
|||
pub struct BlockContext<'a, 'b> {
|
||||
pub window: &'a mut Window,
|
||||
pub context: &'b mut App,
|
||||
pub dimensions: TerminalSize,
|
||||
pub dimensions: TerminalBounds,
|
||||
}
|
||||
|
||||
///A terminal view, maintains the PTY's file handles and communicates with the terminal
|
||||
|
@ -342,7 +342,7 @@ impl TerminalView {
|
|||
return Pixels::ZERO;
|
||||
};
|
||||
|
||||
let line_height = terminal.last_content().size.line_height;
|
||||
let line_height = terminal.last_content().terminal_bounds.line_height;
|
||||
let mut terminal_lines = terminal.total_lines();
|
||||
let viewport_lines = terminal.viewport_lines();
|
||||
if terminal.total_lines() == terminal.viewport_lines() {
|
||||
|
@ -366,16 +366,11 @@ impl TerminalView {
|
|||
max_scroll_top_in_lines as f32 * line_height
|
||||
}
|
||||
|
||||
fn scroll_wheel(
|
||||
&mut self,
|
||||
event: &ScrollWheelEvent,
|
||||
origin: gpui::Point<Pixels>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn scroll_wheel(&mut self, event: &ScrollWheelEvent, cx: &mut Context<Self>) {
|
||||
let terminal_content = self.terminal.read(cx).last_content();
|
||||
|
||||
if self.block_below_cursor.is_some() && terminal_content.display_offset == 0 {
|
||||
let line_height = terminal_content.size.line_height;
|
||||
let line_height = terminal_content.terminal_bounds.line_height;
|
||||
let y_delta = event.delta.pixel_delta(line_height).y;
|
||||
if y_delta < Pixels::ZERO || self.scroll_top > Pixels::ZERO {
|
||||
self.scroll_top = cmp::max(
|
||||
|
@ -387,8 +382,7 @@ impl TerminalView {
|
|||
}
|
||||
}
|
||||
|
||||
self.terminal
|
||||
.update(cx, |term, _| term.scroll_wheel(event, origin));
|
||||
self.terminal.update(cx, |term, _| term.scroll_wheel(event));
|
||||
}
|
||||
|
||||
fn scroll_line_up(&mut self, _: &ScrollLineUp, _: &mut Window, cx: &mut Context<Self>) {
|
||||
|
@ -397,7 +391,7 @@ impl TerminalView {
|
|||
&& terminal_content.display_offset == 0
|
||||
&& self.scroll_top > Pixels::ZERO
|
||||
{
|
||||
let line_height = terminal_content.size.line_height;
|
||||
let line_height = terminal_content.terminal_bounds.line_height;
|
||||
self.scroll_top = cmp::max(self.scroll_top - line_height, Pixels::ZERO);
|
||||
return;
|
||||
}
|
||||
|
@ -411,7 +405,7 @@ impl TerminalView {
|
|||
if self.block_below_cursor.is_some() && terminal_content.display_offset == 0 {
|
||||
let max_scroll_top = self.max_scroll_top(cx);
|
||||
if self.scroll_top < max_scroll_top {
|
||||
let line_height = terminal_content.size.line_height;
|
||||
let line_height = terminal_content.terminal_bounds.line_height;
|
||||
self.scroll_top = cmp::min(self.scroll_top + line_height, max_scroll_top);
|
||||
}
|
||||
return;
|
||||
|
@ -425,7 +419,12 @@ impl TerminalView {
|
|||
if self.scroll_top == Pixels::ZERO {
|
||||
self.terminal.update(cx, |term, _| term.scroll_page_up());
|
||||
} else {
|
||||
let line_height = self.terminal.read(cx).last_content.size.line_height();
|
||||
let line_height = self
|
||||
.terminal
|
||||
.read(cx)
|
||||
.last_content
|
||||
.terminal_bounds
|
||||
.line_height();
|
||||
let visible_block_lines = (self.scroll_top / line_height) as usize;
|
||||
let viewport_lines = self.terminal.read(cx).viewport_lines();
|
||||
let visible_content_lines = viewport_lines - visible_block_lines;
|
||||
|
@ -866,7 +865,8 @@ fn subscribe_for_terminal_events(
|
|||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
};
|
||||
cx.notify()
|
||||
}
|
||||
|
||||
Event::Open(maybe_navigation_target) => match maybe_navigation_target {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue