diff options
Diffstat (limited to 'alacritty/src/input.rs')
-rw-r--r-- | alacritty/src/input.rs | 163 |
1 files changed, 63 insertions, 100 deletions
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 0d6a066d..c5f41b6e 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -71,7 +71,6 @@ pub trait ActionContext<T: EventListener> { fn selection_is_empty(&self) -> bool; fn mouse_mut(&mut self) -> &mut Mouse; fn mouse(&self) -> &Mouse; - fn mouse_coords(&self) -> Option<Point>; fn received_count(&mut self) -> &mut usize; fn suppress_chars(&mut self) -> &mut bool; fn modifiers(&mut self) -> &mut ModifiersState; @@ -100,12 +99,7 @@ pub trait ActionContext<T: EventListener> { fn search_pop_word(&mut self) {} fn search_history_previous(&mut self) {} fn search_history_next(&mut self) {} - fn search_next( - &mut self, - origin: Point<usize>, - direction: Direction, - side: Side, - ) -> Option<Match>; + fn search_next(&mut self, origin: Point, direction: Direction, side: Side) -> Option<Match>; fn advance_search_origin(&mut self, _direction: Direction) {} fn search_direction(&self) -> Direction; fn search_active(&self) -> bool; @@ -121,8 +115,7 @@ impl Action { A: ActionContext<T>, T: EventListener, { - let cursor_point = ctx.terminal().vi_mode_cursor.point; - ctx.toggle_selection(ty, cursor_point, Side::Left); + ctx.toggle_selection(ty, ctx.terminal().vi_mode_cursor.point, Side::Left); // Make sure initial selection is not empty. if let Some(selection) = &mut ctx.terminal_mut().selection { @@ -171,17 +164,19 @@ impl<T: EventListener> Execute<T> for Action { }, Action::ViAction(ViAction::Open) => { ctx.mouse_mut().block_url_launcher = false; - if let Some(url) = ctx.urls().find_at(ctx.terminal().vi_mode_cursor.point) { + let vi_point = ctx.terminal().vi_mode_cursor.point; + let line = (vi_point.line + ctx.terminal().grid().display_offset()).0 as usize; + if let Some(url) = ctx.urls().find_at(Point::new(line, vi_point.column)) { ctx.launch_url(url); } }, Action::ViAction(ViAction::SearchNext) => { let terminal = ctx.terminal(); let direction = ctx.search_direction(); - let vi_point = terminal.visible_to_buffer(terminal.vi_mode_cursor.point); + let vi_point = terminal.vi_mode_cursor.point; let origin = match direction { - Direction::Right => vi_point.add_absolute(terminal, Boundary::Wrap, 1), - Direction::Left => vi_point.sub_absolute(terminal, Boundary::Wrap, 1), + Direction::Right => vi_point.add(terminal, Boundary::None, 1), + Direction::Left => vi_point.sub(terminal, Boundary::None, 1), }; if let Some(regex_match) = ctx.search_next(origin, direction, Side::Left) { @@ -192,10 +187,10 @@ impl<T: EventListener> Execute<T> for Action { Action::ViAction(ViAction::SearchPrevious) => { let terminal = ctx.terminal(); let direction = ctx.search_direction().opposite(); - let vi_point = terminal.visible_to_buffer(terminal.vi_mode_cursor.point); + let vi_point = terminal.vi_mode_cursor.point; let origin = match direction { - Direction::Right => vi_point.add_absolute(terminal, Boundary::Wrap, 1), - Direction::Left => vi_point.sub_absolute(terminal, Boundary::Wrap, 1), + Direction::Right => vi_point.add(terminal, Boundary::None, 1), + Direction::Left => vi_point.sub(terminal, Boundary::None, 1), }; if let Some(regex_match) = ctx.search_next(origin, direction, Side::Left) { @@ -205,9 +200,7 @@ impl<T: EventListener> Execute<T> for Action { }, Action::ViAction(ViAction::SearchStart) => { let terminal = ctx.terminal(); - let origin = terminal - .visible_to_buffer(terminal.vi_mode_cursor.point) - .sub_absolute(terminal, Boundary::Wrap, 1); + let origin = terminal.vi_mode_cursor.point.sub(terminal, Boundary::None, 1); if let Some(regex_match) = ctx.search_next(origin, Direction::Left, Side::Left) { ctx.terminal_mut().vi_goto_point(*regex_match.start()); @@ -216,9 +209,7 @@ impl<T: EventListener> Execute<T> for Action { }, Action::ViAction(ViAction::SearchEnd) => { let terminal = ctx.terminal(); - let origin = terminal - .visible_to_buffer(terminal.vi_mode_cursor.point) - .add_absolute(terminal, Boundary::Wrap, 1); + let origin = terminal.vi_mode_cursor.point.add(terminal, Boundary::None, 1); if let Some(regex_match) = ctx.search_next(origin, Direction::Right, Side::Right) { ctx.terminal_mut().vi_goto_point(*regex_match.end()); @@ -273,7 +264,7 @@ impl<T: EventListener> Execute<T> for Action { Action::ScrollPageUp => { // Move vi mode cursor. let term = ctx.terminal_mut(); - let scroll_lines = term.screen_lines().0 as isize; + let scroll_lines = term.screen_lines() as i32; term.vi_mode_cursor = term.vi_mode_cursor.scroll(term, scroll_lines); ctx.scroll(Scroll::PageUp); @@ -281,7 +272,7 @@ impl<T: EventListener> Execute<T> for Action { Action::ScrollPageDown => { // Move vi mode cursor. let term = ctx.terminal_mut(); - let scroll_lines = -(term.screen_lines().0 as isize); + let scroll_lines = -(term.screen_lines() as i32); term.vi_mode_cursor = term.vi_mode_cursor.scroll(term, scroll_lines); ctx.scroll(Scroll::PageDown); @@ -289,7 +280,7 @@ impl<T: EventListener> Execute<T> for Action { Action::ScrollHalfPageUp => { // Move vi mode cursor. let term = ctx.terminal_mut(); - let scroll_lines = term.screen_lines().0 as isize / 2; + let scroll_lines = term.screen_lines() as i32 / 2; term.vi_mode_cursor = term.vi_mode_cursor.scroll(term, scroll_lines); ctx.scroll(Scroll::Delta(scroll_lines)); @@ -297,37 +288,19 @@ impl<T: EventListener> Execute<T> for Action { Action::ScrollHalfPageDown => { // Move vi mode cursor. let term = ctx.terminal_mut(); - let scroll_lines = -(term.screen_lines().0 as isize / 2); + let scroll_lines = -(term.screen_lines() as i32 / 2); term.vi_mode_cursor = term.vi_mode_cursor.scroll(term, scroll_lines); ctx.scroll(Scroll::Delta(scroll_lines)); }, - Action::ScrollLineUp => { - // Move vi mode cursor. - let term = ctx.terminal(); - if term.grid().display_offset() != term.history_size() - && term.vi_mode_cursor.point.line + 1 != term.screen_lines() - { - ctx.terminal_mut().vi_mode_cursor.point.line += 1; - } - - ctx.scroll(Scroll::Delta(1)); - }, - Action::ScrollLineDown => { - // Move vi mode cursor. - if ctx.terminal().grid().display_offset() != 0 - && ctx.terminal().vi_mode_cursor.point.line.0 != 0 - { - ctx.terminal_mut().vi_mode_cursor.point.line -= 1; - } - - ctx.scroll(Scroll::Delta(-1)); - }, + Action::ScrollLineUp => ctx.scroll(Scroll::Delta(1)), + Action::ScrollLineDown => ctx.scroll(Scroll::Delta(-1)), Action::ScrollToTop => { ctx.scroll(Scroll::Top); // Move vi mode cursor. - ctx.terminal_mut().vi_mode_cursor.point.line = Line(0); + let topmost_line = ctx.terminal().topmost_line(); + ctx.terminal_mut().vi_mode_cursor.point.line = topmost_line; ctx.terminal_mut().vi_motion(ViMotion::FirstOccupied); ctx.mark_dirty(); }, @@ -336,7 +309,7 @@ impl<T: EventListener> Execute<T> for Action { // Move vi mode cursor. let term = ctx.terminal_mut(); - term.vi_mode_cursor.point.line = term.screen_lines() - 1; + term.vi_mode_cursor.point.line = term.bottommost_line(); // Move to beginning twice, to always jump across linewraps. term.vi_motion(ViMotion::FirstOccupied); @@ -414,11 +387,10 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { self.ctx.mouse_mut().y = y; let inside_text_area = size_info.contains_point(x, y); - let point = size_info.pixels_to_coords(x, y); - let cell_side = self.get_mouse_side(); + let point = self.coords_to_point(x, y); + let cell_side = self.cell_side(x); - let cell_changed = - point.line != self.ctx.mouse().line || point.column != self.ctx.mouse().column; + let cell_changed = point != self.ctx.mouse().point; // Update mouse state and check for URL change. let mouse_state = self.mouse_state(); @@ -435,14 +407,15 @@ 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().line = point.line; - self.ctx.mouse_mut().column = point.column; + self.ctx.mouse_mut().point = point; // Don't launch URLs if mouse has moved. self.ctx.mouse_mut().block_url_launcher = true; if (lmb_pressed || rmb_pressed) && (self.ctx.modifiers().shift() || !self.ctx.mouse_mode()) { + let line = Line(point.line as i32) - self.ctx.terminal().grid().display_offset(); + let point = Point::new(line, point.column); self.ctx.update_selection(point, cell_side); } else if cell_changed && point.line < self.ctx.terminal().screen_lines() @@ -460,9 +433,26 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { } } - fn get_mouse_side(&self) -> Side { + /// 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(); - let x = self.ctx.mouse().x; let cell_x = x.saturating_sub(size_info.padding_x() as usize) % size_info.cell_width() as usize; @@ -483,12 +473,12 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { } fn normal_mouse_report(&mut self, button: u8) { - let (line, column) = (self.ctx.mouse().line, self.ctx.mouse().column); + let Point { line, column } = self.ctx.mouse().point; let utf8 = self.ctx.terminal().mode().contains(TermMode::UTF8_MOUSE); let max_point = if utf8 { 2015 } else { 223 }; - if line >= Line(max_point) || column >= Column(max_point) { + if line >= max_point || column >= Column(max_point) { return; } @@ -507,17 +497,17 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { msg.push(32 + 1 + column.0 as u8); } - if utf8 && line >= Line(95) { - msg.append(&mut mouse_pos_encode(line.0)); + if utf8 && line >= 95 { + msg.append(&mut mouse_pos_encode(line)); } else { - msg.push(32 + 1 + line.0 as u8); + msg.push(32 + 1 + line as u8); } self.ctx.write_to_pty(msg); } fn sgr_mouse_report(&mut self, button: u8, state: ElementState) { - let (line, column) = (self.ctx.mouse().line, self.ctx.mouse().column); + let Point { line, column } = self.ctx.mouse().point; let c = match state { ElementState::Pressed => 'M', ElementState::Released => 'm', @@ -589,9 +579,10 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { }; // Load mouse point, treating message bar and padding as the closest cell. - let mouse = self.ctx.mouse(); - let mut point = self.ctx.size_info().pixels_to_coords(mouse.x, mouse.y); - point.line = min(point.line, self.ctx.terminal().screen_lines() - 1); + let point = self.ctx.mouse().point; + let display_offset = self.ctx.terminal().grid().display_offset(); + let absolute_line = Line(point.line as i32) - display_offset; + let point = Point::new(absolute_line, point.column); match button { MouseButton::Left => self.on_left_click(point), @@ -751,24 +742,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { let lines = self.ctx.mouse().scroll_px / height; - // Store absolute position of vi mode cursor. - let term = self.ctx.terminal(); - let absolute = term.visible_to_buffer(term.vi_mode_cursor.point); - - self.ctx.scroll(Scroll::Delta(lines as isize)); - - // Try to restore vi mode cursor position, to keep it above its previous content. - let term = self.ctx.terminal_mut(); - term.vi_mode_cursor.point = term.grid().clamp_buffer_to_visible(absolute); - term.vi_mode_cursor.point.column = absolute.column; - - // Update selection. - if term.mode().contains(TermMode::VI) { - let point = term.vi_mode_cursor.point; - if !self.ctx.selection_is_empty() { - self.ctx.update_selection(point, Side::Right); - } - } + self.ctx.scroll(Scroll::Delta(lines as i32)); } self.ctx.mouse_mut().scroll_px %= height; @@ -977,13 +951,13 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { // Calculate Y position of the end of the last terminal line. let size = self.ctx.size_info(); let terminal_end = size.padding_y() as usize - + size.cell_height() as usize * (size.screen_lines().0 + search_height); + + size.cell_height() as usize * (size.screen_lines() + search_height); let mouse = self.ctx.mouse(); if self.ctx.message().is_none() || (mouse.y <= terminal_end) { None } else if mouse.y <= terminal_end + size.cell_height() as usize - && mouse.column + message_bar::CLOSE_BUTTON_TEXT.len() >= size.cols() + && mouse.point.column + message_bar::CLOSE_BUTTON_TEXT.len() >= size.columns() { Some(MouseState::MessageBarButton) } else { @@ -1055,7 +1029,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { // Compute the height of the scrolling areas. let end_top = max(min_height, size.padding_y() as i32); - let text_area_bottom = size.padding_y() + size.screen_lines().0 as f32 * size.cell_height(); + let text_area_bottom = size.padding_y() + size.screen_lines() as f32 * size.cell_height(); let start_bottom = min(size.height() as i32 - min_height, text_area_bottom as i32); // Get distance from closest window boundary. @@ -1069,7 +1043,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { }; // Scale number of lines scrolled based on distance to boundary. - let delta = delta as isize / step as isize; + let delta = delta as i32 / step as i32; let event = Event::Scroll(Scroll::Delta(delta)); // Schedule event. @@ -1120,7 +1094,7 @@ mod tests { impl<'a, T: EventListener> super::ActionContext<T> for ActionContext<'a, T> { fn search_next( &mut self, - _origin: Point<usize>, + _origin: Point, _direction: Direction, _side: Side, ) -> Option<Match> { @@ -1155,17 +1129,6 @@ mod tests { self.terminal.scroll_display(scroll); } - fn mouse_coords(&self) -> Option<Point> { - let x = self.mouse.x as usize; - let y = self.mouse.y as usize; - - if self.size_info.contains_point(x, y) { - Some(self.size_info.pixels_to_coords(x, y)) - } else { - None - } - } - fn mouse_mode(&self) -> bool { false } |