aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2020-04-10 21:23:50 +0300
committerGitHub <noreply@github.com>2020-04-10 21:23:50 +0300
commitf14d24542c3ceda3b508c707eb79cf2fe2a04bd1 (patch)
tree8f91c80296644b278733b412127244c2a84bb348
parent2fc5120327c6eb096154214faec5dc4e1dee2253 (diff)
downloadalacritty-f14d24542c3ceda3b508c707eb79cf2fe2a04bd1.tar.gz
alacritty-f14d24542c3ceda3b508c707eb79cf2fe2a04bd1.zip
Fix various mouse mode + vi mode interactions
This commit fixes some issues introduced by 1a8cd172e520e493bacc9c6a2ae6f80de086eaa3: 1. Vi cursor not moving properly on double/triple click 2. URL not launching via mouse click in vi mode + mouse mode 3. Ability to select in mouse mode with double/triple click regardless of shift modifier
-rw-r--r--alacritty/src/display.rs3
-rw-r--r--alacritty/src/event.rs6
-rw-r--r--alacritty/src/input.rs176
3 files changed, 90 insertions, 95 deletions
diff --git a/alacritty/src/display.rs b/alacritty/src/display.rs
index 6d5d810d..c456fda8 100644
--- a/alacritty/src/display.rs
+++ b/alacritty/src/display.rs
@@ -364,7 +364,8 @@ impl Display {
let size_info = self.size_info;
let selection = !terminal.selection().as_ref().map(Selection::is_empty).unwrap_or(true);
- let mouse_mode = terminal.mode().intersects(TermMode::MOUSE_MODE);
+ let mouse_mode = terminal.mode().intersects(TermMode::MOUSE_MODE)
+ && !terminal.mode().contains(TermMode::VI);
let vi_mode_cursor = if terminal.mode().contains(TermMode::VI) {
Some(terminal.vi_mode_cursor)
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index 89aa8be6..e532ac12 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -12,7 +12,7 @@ use std::sync::Arc;
use std::time::Instant;
use glutin::dpi::PhysicalSize;
-use glutin::event::{ElementState, Event as GlutinEvent, ModifiersState, MouseButton, WindowEvent};
+use glutin::event::{ElementState, Event as GlutinEvent, ModifiersState, WindowEvent};
use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindowTarget};
use glutin::platform::desktop::EventLoopExtDesktop;
#[cfg(not(any(target_os = "macos", windows)))]
@@ -295,7 +295,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
}
}
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq)]
pub enum ClickState {
None,
Click,
@@ -319,7 +319,6 @@ pub struct Mouse {
pub cell_side: Side,
pub lines_scrolled: f32,
pub block_url_launcher: bool,
- pub last_button: MouseButton,
pub inside_grid: bool,
}
@@ -339,7 +338,6 @@ impl Default for Mouse {
cell_side: Side::Left,
lines_scrolled: 0.,
block_url_launcher: false,
- last_button: MouseButton::Other(0),
inside_grid: false,
}
}
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs
index 7c2a1f8b..b84c9a53 100644
--- a/alacritty/src/input.rs
+++ b/alacritty/src/input.rs
@@ -455,89 +455,79 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
}
}
- fn on_mouse_double_click(&mut self, button: MouseButton, point: Point) {
- if button == MouseButton::Left {
- let side = self.ctx.mouse().cell_side;
- self.ctx.start_selection(SelectionType::Semantic, point, side);
- }
- }
+ fn on_mouse_press(&mut self, button: MouseButton) {
+ // Handle mouse mode
+ if !self.ctx.modifiers().shift() && self.ctx.mouse_mode() {
+ self.ctx.mouse_mut().click_state = ClickState::None;
+
+ let code = match button {
+ MouseButton::Left => 0,
+ MouseButton::Middle => 1,
+ MouseButton::Right => 2,
+ // Can't properly report more than three buttons.
+ MouseButton::Other(_) => return,
+ };
- fn on_mouse_triple_click(&mut self, button: MouseButton, point: Point) {
- if button == MouseButton::Left {
- let side = self.ctx.mouse().cell_side;
- self.ctx.start_selection(SelectionType::Lines, point, side);
+ 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;
}
}
- fn on_mouse_press(&mut self, button: MouseButton) {
+ /// 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 = self.ctx.mouse().last_click_timestamp.elapsed();
+ let elapsed = now - self.ctx.mouse().last_click_timestamp;
self.ctx.mouse_mut().last_click_timestamp = now;
- let button_changed = self.ctx.mouse().last_button != button;
-
// 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);
+ let side = self.ctx.mouse().cell_side;
+
self.ctx.mouse_mut().click_state = match self.ctx.mouse().click_state {
ClickState::Click
- if !button_changed
- && elapsed < self.ctx.config().ui_config.mouse.double_click.threshold =>
+ if elapsed < self.ctx.config().ui_config.mouse.double_click.threshold =>
{
self.ctx.mouse_mut().block_url_launcher = true;
- self.on_mouse_double_click(button, point);
+ self.ctx.start_selection(SelectionType::Semantic, point, side);
ClickState::DoubleClick
}
ClickState::DoubleClick
- if !button_changed
- && elapsed < self.ctx.config().ui_config.mouse.triple_click.threshold =>
+ if elapsed < self.ctx.config().ui_config.mouse.triple_click.threshold =>
{
self.ctx.mouse_mut().block_url_launcher = true;
- self.on_mouse_triple_click(button, point);
+ self.ctx.start_selection(SelectionType::Lines, point, side);
ClickState::TripleClick
}
_ => {
- if button == MouseButton::Left
- && (self.ctx.modifiers().shift()
- || !self.ctx.terminal().mode().intersects(TermMode::MOUSE_MODE))
- {
- // Don't launch URLs if this click cleared the selection
- self.ctx.mouse_mut().block_url_launcher = !self.ctx.selection_is_empty();
-
- self.ctx.clear_selection();
-
- // Start new empty selection
- let side = self.ctx.mouse().cell_side;
- if self.ctx.modifiers().ctrl() {
- self.ctx.start_selection(SelectionType::Block, point, side);
- } else {
- self.ctx.start_selection(SelectionType::Simple, point, side);
- }
+ // Don't launch URLs if this click cleared the selection
+ self.ctx.mouse_mut().block_url_launcher = !self.ctx.selection_is_empty();
- // Move vi mode cursor to mouse position
- if self.ctx.terminal().mode().contains(TermMode::VI) {
- // Update vi mode cursor position on click
- self.ctx.terminal_mut().vi_mode_cursor.point = point;
- }
- }
+ self.ctx.clear_selection();
- if !self.ctx.modifiers().shift() && self.ctx.mouse_mode() {
- let code = match button {
- MouseButton::Left => 0,
- MouseButton::Middle => 1,
- MouseButton::Right => 2,
- // Can't properly report more than three buttons.
- MouseButton::Other(_) => return,
- };
- self.mouse_report(code, ElementState::Pressed);
- return;
+ // Start new empty selection
+ if self.ctx.modifiers().ctrl() {
+ self.ctx.start_selection(SelectionType::Block, point, side);
+ } else {
+ self.ctx.start_selection(SelectionType::Simple, point, side);
}
ClickState::Click
},
};
+
+ // Move vi mode cursor to mouse position
+ if self.ctx.terminal().mode().contains(TermMode::VI) {
+ // Update Vi mode cursor position on click
+ self.ctx.terminal_mut().vi_mode_cursor.point = point;
+ }
}
fn on_mouse_release(&mut self, button: MouseButton) {
@@ -695,8 +685,6 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
ElementState::Released => self.on_mouse_release(button),
}
}
-
- self.ctx.mouse_mut().last_button = button;
}
/// Process key input.
@@ -910,20 +898,12 @@ mod tests {
fn send_event(&self, _event: TerminalEvent) {}
}
- #[derive(Debug, PartialEq)]
- enum MultiClick {
- DoubleClick,
- TripleClick,
- None,
- }
-
struct ActionContext<'a, T> {
pub terminal: &'a mut Term<T>,
pub selection: &'a mut Option<Selection>,
pub size_info: &'a SizeInfo,
pub mouse: &'a mut Mouse,
pub message_buffer: &'a mut MessageBuffer,
- pub last_action: MultiClick,
pub received_count: usize,
pub suppress_chars: bool,
pub modifiers: ModifiersState,
@@ -935,13 +915,7 @@ mod tests {
fn update_selection(&mut self, _point: Point, _side: Side) {}
- fn start_selection(&mut self, ty: SelectionType, _point: Point, _side: Side) {
- match ty {
- SelectionType::Semantic => self.last_action = MultiClick::DoubleClick,
- SelectionType::Lines => self.last_action = MultiClick::TripleClick,
- _ => (),
- }
- }
+ fn start_selection(&mut self, _ty: SelectionType, _point: Point, _side: Side) {}
fn toggle_selection(&mut self, _ty: SelectionType, _point: Point, _side: Side) {}
@@ -1051,8 +1025,7 @@ mod tests {
initial_state: $initial_state:expr,
initial_button: $initial_button:expr,
input: $input:expr,
- end_state: $end_state:pat,
- last_action: $last_action:expr
+ end_state: $end_state:expr,
} => {
#[test]
fn $name() {
@@ -1082,7 +1055,6 @@ mod tests {
let mut mouse = Mouse::default();
mouse.click_state = $initial_state;
- mouse.last_button = $initial_button;
let mut selection = None;
@@ -1093,7 +1065,6 @@ mod tests {
selection: &mut selection,
mouse: &mut mouse,
size_info: &size,
- last_action: MultiClick::None,
received_count: 0,
suppress_chars: false,
modifiers: Default::default(),
@@ -1116,10 +1087,7 @@ mod tests {
processor.mouse_input(state, button);
};
- assert!(match processor.ctx.mouse.click_state {
- $end_state => processor.ctx.last_action == $last_action,
- _ => false
- });
+ assert_eq!(processor.ctx.mouse.click_state, $end_state);
}
}
}
@@ -1151,13 +1119,44 @@ mod tests {
event: WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
- device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ device_id: unsafe { std::mem::transmute_copy(&0) },
modifiers: ModifiersState::default(),
},
- window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ window_id: unsafe { std::mem::transmute_copy(&0) },
},
end_state: ClickState::Click,
- last_action: MultiClick::None
+ }
+
+ test_clickstate! {
+ name: single_right_click,
+ initial_state: ClickState::None,
+ initial_button: MouseButton::Other(0),
+ input: Event::WindowEvent {
+ event: WindowEvent::MouseInput {
+ state: ElementState::Pressed,
+ button: MouseButton::Right,
+ device_id: unsafe { std::mem::transmute_copy(&0) },
+ modifiers: ModifiersState::default(),
+ },
+ window_id: unsafe { std::mem::transmute_copy(&0) },
+ },
+ end_state: ClickState::None,
+ }
+
+ test_clickstate! {
+ name: single_middle_click,
+ initial_state: ClickState::None,
+ initial_button: MouseButton::Other(0),
+ input: Event::WindowEvent {
+ event: WindowEvent::MouseInput {
+ state: ElementState::Pressed,
+ button: MouseButton::Middle,
+ device_id: unsafe { std::mem::transmute_copy(&0) },
+ modifiers: ModifiersState::default(),
+ },
+ window_id: unsafe { std::mem::transmute_copy(&0) },
+ },
+ end_state: ClickState::None,
}
test_clickstate! {
@@ -1168,13 +1167,12 @@ mod tests {
event: WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
- device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ device_id: unsafe { std::mem::transmute_copy(&0) },
modifiers: ModifiersState::default(),
},
- window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ window_id: unsafe { std::mem::transmute_copy(&0) },
},
end_state: ClickState::DoubleClick,
- last_action: MultiClick::DoubleClick
}
test_clickstate! {
@@ -1185,13 +1183,12 @@ mod tests {
event: WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
- device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ device_id: unsafe { std::mem::transmute_copy(&0) },
modifiers: ModifiersState::default(),
},
- window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ window_id: unsafe { std::mem::transmute_copy(&0) },
},
end_state: ClickState::TripleClick,
- last_action: MultiClick::TripleClick
}
test_clickstate! {
@@ -1202,13 +1199,12 @@ mod tests {
event: WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Right,
- device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ device_id: unsafe { std::mem::transmute_copy(&0) },
modifiers: ModifiersState::default(),
},
- window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ window_id: unsafe { std::mem::transmute_copy(&0) },
},
- end_state: ClickState::Click,
- last_action: MultiClick::None
+ end_state: ClickState::None,
}
test_process_binding! {