Fix selection scrolling with message bar visible

This resolves an issue with selection scrolling which would cause the
selection to wrap to the top of the screen once the cursor enters the
padding below the message bar.

Fixes #4120.
This commit is contained in:
Christian Duerr 2020-08-14 07:26:42 +00:00 committed by GitHub
parent 0a1683e84d
commit 0003f6683f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 33 deletions

View File

@ -34,6 +34,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Slow rendering performance with HiDPI displays, especially on macOS - Slow rendering performance with HiDPI displays, especially on macOS
- Keys swallowed during search when pressing them right before releasing backspace - Keys swallowed during search when pressing them right before releasing backspace
- Crash when a wrapped line is rotated into the last line - Crash when a wrapped line is rotated into the last line
- Selection wrapping to the top when selecting below the error/warning bar
## 0.5.0 ## 0.5.0

View File

@ -170,9 +170,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
} else if self.mouse().left_button_state == ElementState::Pressed } else if self.mouse().left_button_state == ElementState::Pressed
|| self.mouse().right_button_state == ElementState::Pressed || self.mouse().right_button_state == ElementState::Pressed
{ {
let (x, y) = (self.mouse().x, self.mouse().y); let point = self.size_info().pixels_to_coords(self.mouse().x, self.mouse().y);
let size_info = self.size_info();
let point = size_info.pixels_to_coords(x, y);
let cell_side = self.mouse().cell_side; let cell_side = self.mouse().cell_side;
self.update_selection(Point { line: point.line, col: point.col }, cell_side); self.update_selection(Point { line: point.line, col: point.col }, cell_side);
} }
@ -195,20 +193,27 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
self.terminal.dirty = true; self.terminal.dirty = true;
} }
fn update_selection(&mut self, point: Point, side: Side) { fn update_selection(&mut self, mut point: Point, side: Side) {
let point = self.terminal.visible_to_buffer(point); let mut selection = match self.terminal.selection.take() {
Some(selection) => selection,
None => return,
};
// Update selection if one exists. // Treat motion over message bar like motion over the last line.
let vi_mode = self.terminal.mode().contains(TermMode::VI); point.line = min(point.line, self.terminal.screen_lines() - 1);
if let Some(selection) = &mut self.terminal.selection {
selection.update(point, side);
if vi_mode { // Update selection.
selection.include_all(); let absolute_point = self.terminal.visible_to_buffer(point);
} selection.update(absolute_point, side);
self.terminal.dirty = true; // Move vi cursor and expand selection.
if self.terminal.mode().contains(TermMode::VI) {
self.terminal.vi_mode_cursor.point = point;
selection.include_all();
} }
self.terminal.selection = Some(selection);
self.terminal.dirty = true;
} }
fn start_selection(&mut self, ty: SelectionType, point: Point, side: Side) { fn start_selection(&mut self, ty: SelectionType, point: Point, side: Side) {
@ -646,7 +651,7 @@ pub struct Mouse {
pub cell_side: Side, pub cell_side: Side,
pub lines_scrolled: f32, pub lines_scrolled: f32,
pub block_url_launcher: bool, pub block_url_launcher: bool,
pub inside_grid: bool, pub inside_text_area: bool,
} }
impl Default for Mouse { impl Default for Mouse {
@ -666,7 +671,7 @@ impl Default for Mouse {
cell_side: Side::Left, cell_side: Side::Left,
lines_scrolled: 0., lines_scrolled: 0.,
block_url_launcher: false, block_url_launcher: false,
inside_grid: false, inside_text_area: false,
} }
} }
} }
@ -985,7 +990,7 @@ impl<N: Notify + OnResize> Processor<N> {
processor.ctx.write_to_pty((path + " ").into_bytes()); processor.ctx.write_to_pty((path + " ").into_bytes());
}, },
WindowEvent::CursorLeft { .. } => { WindowEvent::CursorLeft { .. } => {
processor.ctx.mouse.inside_grid = false; processor.ctx.mouse.inside_text_area = false;
if processor.highlighted_url.is_some() { if processor.highlighted_url.is_some() {
processor.ctx.terminal.dirty = true; processor.ctx.terminal.dirty = true;

View File

@ -377,7 +377,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
self.ctx.mouse_mut().x = x; self.ctx.mouse_mut().x = x;
self.ctx.mouse_mut().y = y; self.ctx.mouse_mut().y = y;
let inside_grid = size_info.contains_point(x, y); let inside_text_area = size_info.contains_point(x, y);
let point = size_info.pixels_to_coords(x, y); let point = size_info.pixels_to_coords(x, y);
let cell_side = self.get_mouse_side(); let cell_side = self.get_mouse_side();
@ -387,12 +387,12 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
// If the mouse hasn't changed cells, do nothing. // If the mouse hasn't changed cells, do nothing.
if !cell_changed if !cell_changed
&& self.ctx.mouse().cell_side == cell_side && self.ctx.mouse().cell_side == cell_side
&& self.ctx.mouse().inside_grid == inside_grid && self.ctx.mouse().inside_text_area == inside_text_area
{ {
return; return;
} }
self.ctx.mouse_mut().inside_grid = inside_grid; self.ctx.mouse_mut().inside_text_area = inside_text_area;
self.ctx.mouse_mut().cell_side = cell_side; self.ctx.mouse_mut().cell_side = cell_side;
self.ctx.mouse_mut().line = point.line; self.ctx.mouse_mut().line = point.line;
self.ctx.mouse_mut().column = point.col; self.ctx.mouse_mut().column = point.col;
@ -405,23 +405,14 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
self.update_url_state(&mouse_state); self.update_url_state(&mouse_state);
self.ctx.window_mut().set_mouse_cursor(mouse_state.into()); self.ctx.window_mut().set_mouse_cursor(mouse_state.into());
let last_term_line = self.ctx.terminal().grid().screen_lines() - 1;
if (lmb_pressed || rmb_pressed) if (lmb_pressed || rmb_pressed)
&& (self.ctx.modifiers().shift() || !self.ctx.mouse_mode()) && (self.ctx.modifiers().shift() || !self.ctx.mouse_mode())
&& !search_active && !search_active
{ {
// Treat motion over message bar like motion over the last line. self.ctx.update_selection(point, cell_side);
let line = min(point.line, last_term_line); } else if inside_text_area
// Move vi mode cursor to mouse cursor position.
if self.ctx.terminal().mode().contains(TermMode::VI) {
self.ctx.terminal_mut().vi_mode_cursor.point = point;
}
self.ctx.update_selection(Point { line, col: point.col }, cell_side);
} else if inside_grid
&& cell_changed && cell_changed
&& point.line <= last_term_line && point.line < self.ctx.terminal().screen_lines()
&& self.ctx.terminal().mode().intersects(TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG) && self.ctx.terminal().mode().intersects(TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG)
{ {
if lmb_pressed { if lmb_pressed {
@ -997,7 +988,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
// Since search is above the message bar, the button is offset by search's height. // Since search is above the message bar, the button is offset by search's height.
let search_height = if self.ctx.search_active() { 1 } else { 0 }; let search_height = if self.ctx.search_active() { 1 } else { 0 };
mouse.inside_grid mouse.inside_text_area
&& mouse.column + message_bar::CLOSE_BUTTON_TEXT.len() >= self.ctx.size_info().cols() && mouse.column + message_bar::CLOSE_BUTTON_TEXT.len() >= self.ctx.size_info().cols()
&& mouse.line == self.ctx.terminal().grid().screen_lines() + search_height && mouse.line == self.ctx.terminal().grid().screen_lines() + search_height
} }

View File

@ -163,7 +163,7 @@ impl Urls {
// Make sure all prerequisites for highlighting are met. // Make sure all prerequisites for highlighting are met.
if selection if selection
|| !mouse.inside_grid || !mouse.inside_text_area
|| config.ui_config.mouse.url.launcher.is_none() || config.ui_config.mouse.url.launcher.is_none()
|| required_mods != mods || required_mods != mods
|| mouse.left_button_state == ElementState::Pressed || mouse.left_button_state == ElementState::Pressed