diff options
-rw-r--r-- | alacritty/src/display/mod.rs | 2 | ||||
-rw-r--r-- | alacritty/src/event.rs | 27 | ||||
-rw-r--r-- | alacritty/src/input.rs | 119 |
3 files changed, 76 insertions, 72 deletions
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index 6e40e35c..810d20f3 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -680,7 +680,7 @@ impl Display { } // Find highlighted hint at mouse position. - let point = viewport_to_point(term.grid().display_offset(), mouse.point); + let point = mouse.point(&self.size_info, term.grid().display_offset()); let highlighted_hint = hint::highlighted_at(&term, config, point, modifiers); // Update cursor shape. 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<T> 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<usize>, 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 diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 7dd47803..0fd2b224 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -33,7 +33,7 @@ use crate::config::{Action, BindingMode, Config, Key, SearchAction, ViAction}; use crate::daemon::start_daemon; use crate::display::hint::HintMatch; use crate::display::window::Window; -use crate::display::{self, Display}; +use crate::display::Display; use crate::event::{ClickState, Event, Mouse, TYPING_SEARCH_DELAY}; use crate::message_bar::{self, Message}; use crate::scheduler::{Scheduler, TimerId}; @@ -341,17 +341,19 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { self.update_selection_scrolling(y); } + let display_offset = self.ctx.terminal().grid().display_offset(); + let old_point = self.ctx.mouse().point(&size_info, display_offset); + let x = min(max(x, 0), size_info.width() as i32 - 1) as usize; let y = min(max(y, 0), size_info.height() as i32 - 1) as usize; - self.ctx.mouse_mut().x = x; self.ctx.mouse_mut().y = y; let inside_text_area = size_info.contains_point(x, y); - let point = self.coords_to_point(x, y); let cell_side = self.cell_side(x); - let cell_changed = point != self.ctx.mouse().point; + let point = self.ctx.mouse().point(&size_info, display_offset); + let cell_changed = old_point != point; // If the mouse hasn't changed cells, do nothing. if !cell_changed @@ -363,7 +365,6 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { self.ctx.mouse_mut().inside_text_area = inside_text_area; self.ctx.mouse_mut().cell_side = cell_side; - self.ctx.mouse_mut().point = point; // Update mouse state and check for URL change. let mouse_state = self.cursor_state(); @@ -377,11 +378,8 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { if (lmb_pressed || rmb_pressed) && (self.ctx.modifiers().shift() || !self.ctx.mouse_mode()) { - let display_offset = self.ctx.terminal().grid().display_offset(); - let point = display::viewport_to_point(display_offset, point); self.ctx.update_selection(point, cell_side); } else if cell_changed - && point.line < self.ctx.terminal().screen_lines() && self.ctx.terminal().mode().intersects(TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG) { if lmb_pressed { @@ -396,23 +394,6 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { } } - /// Convert window space pixels to terminal grid coordinates. - /// - /// 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] - fn coords_to_point(&self, x: usize, y: usize) -> Point<usize> { - let size = self.ctx.size_info(); - - let column = x.saturating_sub(size.padding_x() as usize) / (size.cell_width() as usize); - let column = min(Column(column), size.last_column()); - - let line = y.saturating_sub(size.padding_y() as usize) / (size.cell_height() as usize); - let line = min(line, size.bottommost_line().0 as usize); - - Point::new(line, column) - } - /// Check which side of a cell an X coordinate lies on. fn cell_side(&self, x: usize) -> Side { let size_info = self.ctx.size_info(); @@ -435,13 +416,45 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { } } - fn normal_mouse_report(&mut self, button: u8) { - let Point { line, column } = self.ctx.mouse().point; + fn mouse_report(&mut self, button: u8, state: ElementState) { + let display_offset = self.ctx.terminal().grid().display_offset(); + let point = self.ctx.mouse().point(&self.ctx.size_info(), display_offset); + + // Assure the mouse point is not in the scrollback. + if point.line >= 0 { + return; + } + + // Calculate modifiers value. + let mut mods = 0; + let modifiers = self.ctx.modifiers(); + if modifiers.shift() { + mods += 4; + } + if modifiers.alt() { + mods += 8; + } + if modifiers.ctrl() { + mods += 16; + } + + // Report mouse events. + if self.ctx.terminal().mode().contains(TermMode::SGR_MOUSE) { + self.sgr_mouse_report(point, button + mods, state); + } else if let ElementState::Released = state { + self.normal_mouse_report(point, 3 + mods); + } else { + self.normal_mouse_report(point, button + mods); + } + } + + fn normal_mouse_report(&mut self, point: Point, button: u8) { + let Point { line, column } = point; let utf8 = self.ctx.terminal().mode().contains(TermMode::UTF8_MOUSE); let max_point = if utf8 { 2015 } else { 223 }; - if line >= max_point || column >= Column(max_point) { + if line >= max_point || column >= max_point { return; } @@ -461,49 +474,24 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { } if utf8 && line >= 95 { - msg.append(&mut mouse_pos_encode(line)); + msg.append(&mut mouse_pos_encode(line.0 as usize)); } else { - msg.push(32 + 1 + line as u8); + msg.push(32 + 1 + line.0 as u8); } self.ctx.write_to_pty(msg); } - fn sgr_mouse_report(&mut self, button: u8, state: ElementState) { - let Point { line, column } = self.ctx.mouse().point; + fn sgr_mouse_report(&mut self, point: Point, button: u8, state: ElementState) { let c = match state { ElementState::Pressed => 'M', ElementState::Released => 'm', }; - let msg = format!("\x1b[<{};{};{}{}", button, column + 1, line + 1, c); + let msg = format!("\x1b[<{};{};{}{}", button, point.column + 1, point.line + 1, c); self.ctx.write_to_pty(msg.into_bytes()); } - fn mouse_report(&mut self, button: u8, state: ElementState) { - // Calculate modifiers value. - let mut mods = 0; - let modifiers = self.ctx.modifiers(); - if modifiers.shift() { - mods += 4; - } - if modifiers.alt() { - mods += 8; - } - if modifiers.ctrl() { - mods += 16; - } - - // Report mouse events. - if self.ctx.terminal().mode().contains(TermMode::SGR_MOUSE) { - self.sgr_mouse_report(button + mods, state); - } else if let ElementState::Released = state { - self.normal_mouse_report(3 + mods); - } else { - self.normal_mouse_report(button + mods); - } - } - fn on_mouse_press(&mut self, button: MouseButton) { // Handle mouse mode. if !self.ctx.modifiers().shift() && self.ctx.mouse_mode() { @@ -543,7 +531,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { // Load mouse point, treating message bar and padding as the closest cell. let display_offset = self.ctx.terminal().grid().display_offset(); - let point = display::viewport_to_point(display_offset, self.ctx.mouse().point); + let point = self.ctx.mouse().point(&self.ctx.size_info(), display_offset); match button { MouseButton::Left => self.on_left_click(point), @@ -921,10 +909,13 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { + size.cell_height() as usize * (size.screen_lines() + search_height); let mouse = self.ctx.mouse(); + let display_offset = self.ctx.terminal().grid().display_offset(); + let point = self.ctx.mouse().point(&self.ctx.size_info(), display_offset); + if self.ctx.message().is_none() || (mouse.y <= terminal_end) { None } else if mouse.y <= terminal_end + size.cell_height() as usize - && mouse.point.column + message_bar::CLOSE_BUTTON_TEXT.len() >= size.columns() + && point.column + message_bar::CLOSE_BUTTON_TEXT.len() >= size.columns() { Some(CursorIcon::Hand) } else { @@ -934,13 +925,11 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { /// Icon state of the cursor. fn cursor_state(&mut self) -> CursorIcon { - // Define function to check if mouse is on top of a hint. let display_offset = self.ctx.terminal().grid().display_offset(); - let mouse_point = self.ctx.mouse().point; - let hint_highlighted = |hint: &HintMatch| { - let point = display::viewport_to_point(display_offset, mouse_point); - hint.bounds.contains(&point) - }; + let point = self.ctx.mouse().point(&self.ctx.size_info(), display_offset); + + // Function to check if mouse is on top of a hint. + let hint_highlighted = |hint: &HintMatch| hint.bounds.contains(&point); if let Some(mouse_state) = self.message_bar_cursor_state() { mouse_state |