diff options
author | Christian Duerr <contact@christianduerr.com> | 2020-06-23 09:57:15 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-23 12:57:15 +0300 |
commit | 43c0ad6ea9d2467ccf867a310c4f1e30f5b627c6 (patch) | |
tree | 18ca8bad91c9ca47d22fca45222566a462aaa303 /alacritty/src/input.rs | |
parent | 87e5b1aa25ea61937fa5f79668d2a46e88707c5e (diff) | |
download | r-alacritty-43c0ad6ea9d2467ccf867a310c4f1e30f5b627c6.tar.gz r-alacritty-43c0ad6ea9d2467ccf867a310c4f1e30f5b627c6.tar.bz2 r-alacritty-43c0ad6ea9d2467ccf867a310c4f1e30f5b627c6.zip |
Add selection expansion
This allows for expanding the selection using the right mouse button.
The new selection type depends on the number of clicks and applies to
both sides of the selection.
Fixes #1554.
Diffstat (limited to 'alacritty/src/input.rs')
-rw-r--r-- | alacritty/src/input.rs | 113 |
1 files changed, 78 insertions, 35 deletions
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index d43bb26f..b0a6eb80 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -492,44 +492,80 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { }; self.mouse_report(code, ElementState::Pressed); - } else if button == MouseButton::Left { - self.on_left_click(); } else { - // Do nothing when using buttons other than LMB. - self.ctx.mouse_mut().click_state = ClickState::None; + // Calculate time since the last click to handle double/triple clicks. + let now = Instant::now(); + let elapsed = now - self.ctx.mouse().last_click_timestamp; + self.ctx.mouse_mut().last_click_timestamp = now; + + // Update multi-click state. + let mouse_config = &self.ctx.config().ui_config.mouse; + self.ctx.mouse_mut().click_state = match self.ctx.mouse().click_state { + // Reset click state if button has changed. + _ if button != self.ctx.mouse().last_click_button => { + self.ctx.mouse_mut().last_click_button = button; + ClickState::Click + }, + ClickState::Click if elapsed < mouse_config.double_click.threshold => { + ClickState::DoubleClick + }, + ClickState::DoubleClick if elapsed < mouse_config.triple_click.threshold => { + ClickState::TripleClick + }, + _ => ClickState::Click, + }; + + // 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().grid().num_lines() - 1); + + match button { + MouseButton::Left => self.on_left_click(point), + MouseButton::Right => self.on_right_click(point), + // Do nothing when using buttons other than LMB. + _ => self.ctx.mouse_mut().click_state = ClickState::None, + } } } - /// Handle left click selection and vi mode cursor movement. - fn on_left_click(&mut self) { - // Calculate time since the last click to handle double/triple clicks in normal mode. - let now = Instant::now(); - let elapsed = now - self.ctx.mouse().last_click_timestamp; - self.ctx.mouse_mut().last_click_timestamp = now; + /// Handle selection expansion on right click. + fn on_right_click(&mut self, point: Point) { + match self.ctx.mouse().click_state { + ClickState::Click => { + let selection_type = if self.ctx.modifiers().ctrl() { + SelectionType::Block + } else { + SelectionType::Simple + }; - // Load mouse point, treating message bar and padding as 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().grid().num_lines() - 1); + self.expand_selection(point, selection_type); + }, + ClickState::DoubleClick => self.expand_selection(point, SelectionType::Semantic), + ClickState::TripleClick => self.expand_selection(point, SelectionType::Lines), + ClickState::None => (), + } + } + + /// Expand existing selection. + fn expand_selection(&mut self, point: Point, selection_type: SelectionType) { + let cell_side = self.ctx.mouse().cell_side; + + let selection = match &mut self.ctx.terminal_mut().selection { + Some(selection) => selection, + None => return, + }; + + selection.ty = selection_type; + self.ctx.update_selection(point, cell_side); + } + /// Handle left click selection and vi mode cursor movement. + fn on_left_click(&mut self, point: Point) { let side = self.ctx.mouse().cell_side; - self.ctx.mouse_mut().click_state = match self.ctx.mouse().click_state { - ClickState::Click - if elapsed < self.ctx.config().ui_config.mouse.double_click.threshold => - { - self.ctx.mouse_mut().block_url_launcher = true; - self.ctx.start_selection(SelectionType::Semantic, point, side); - ClickState::DoubleClick - } - ClickState::DoubleClick - if elapsed < self.ctx.config().ui_config.mouse.triple_click.threshold => - { - self.ctx.mouse_mut().block_url_launcher = true; - self.ctx.start_selection(SelectionType::Lines, point, side); - ClickState::TripleClick - } - _ => { + match self.ctx.mouse().click_state { + ClickState::Click => { // Don't launch URLs if this click cleared the selection. self.ctx.mouse_mut().block_url_launcher = !self.ctx.selection_is_empty(); @@ -541,9 +577,16 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } else { self.ctx.start_selection(SelectionType::Simple, point, side); } - - ClickState::Click }, + ClickState::DoubleClick => { + self.ctx.mouse_mut().block_url_launcher = true; + self.ctx.start_selection(SelectionType::Semantic, point, side); + }, + ClickState::TripleClick => { + self.ctx.mouse_mut().block_url_launcher = true; + self.ctx.start_selection(SelectionType::Lines, point, side); + }, + ClickState::None => (), }; // Move vi mode cursor to mouse position. @@ -1080,7 +1123,7 @@ mod tests { unimplemented!(); } - fn scheduler_mut (&mut self) -> &mut Scheduler { + fn scheduler_mut(&mut self) -> &mut Scheduler { unimplemented!(); } } @@ -1209,7 +1252,7 @@ mod tests { }, window_id: unsafe { std::mem::transmute_copy(&0) }, }, - end_state: ClickState::None, + end_state: ClickState::Click, } test_clickstate! { @@ -1273,7 +1316,7 @@ mod tests { }, window_id: unsafe { std::mem::transmute_copy(&0) }, }, - end_state: ClickState::None, + end_state: ClickState::Click, } test_process_binding! { |