From 9cb55621f77a8eeca3738013ef9b1274b7a97e96 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Thu, 15 Apr 2021 22:16:31 +0000 Subject: Fix mouse point crash on resize This resolves an issue with Alacritty crashing after a resize, due to the last cached mouse point being out of bounds. Instead of caching the mouse point, it is now computed on demand to make sure it can never be invalid. Fixes #4977. --- alacritty/src/event.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'alacritty/src/event.rs') diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 3b24de0f..e61354b8 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -209,12 +209,12 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon && self.terminal.selection.as_ref().map(|s| s.is_empty()) != Some(true) { self.update_selection(self.terminal.vi_mode_cursor.point, Side::Right); - } else if self.mouse().left_button_state == ElementState::Pressed - || self.mouse().right_button_state == ElementState::Pressed + } else if self.mouse.left_button_state == ElementState::Pressed + || self.mouse.right_button_state == ElementState::Pressed { let display_offset = self.terminal.grid().display_offset(); - let point = display::viewport_to_point(display_offset, self.mouse().point); - self.update_selection(point, self.mouse().cell_side); + let point = self.mouse.point(&self.size_info(), display_offset); + self.update_selection(point, self.mouse.cell_side); } *self.dirty = true; @@ -891,7 +891,6 @@ pub struct Mouse { pub block_hint_launcher: bool, pub hint_highlight_dirty: bool, pub inside_text_area: bool, - pub point: Point, pub x: usize, pub y: usize, } @@ -911,13 +910,29 @@ impl Default for Mouse { inside_text_area: Default::default(), lines_scrolled: Default::default(), scroll_px: Default::default(), - point: Default::default(), x: Default::default(), y: Default::default(), } } } +impl Mouse { + /// Convert mouse pixel coordinates to viewport point. + /// + /// If the coordinates are outside of the terminal grid, like positions inside the padding, the + /// coordinates will be clamped to the closest grid coordinates. + #[inline] + pub fn point(&self, size: &SizeInfo, display_offset: usize) -> Point { + let col = self.x.saturating_sub(size.padding_x() as usize) / (size.cell_width() as usize); + let col = min(Column(col), size.last_column()); + + let line = self.y.saturating_sub(size.padding_y() as usize) / (size.cell_height() as usize); + let line = min(line, size.bottommost_line().0 as usize); + + display::viewport_to_point(display_offset, Point::new(line, col)) + } +} + /// The event processor. /// /// Stores some state from received events and dispatches actions when they are -- cgit