diff options
author | Christian Duerr <contact@christianduerr.com> | 2019-11-11 22:05:24 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-11 22:05:24 +0100 |
commit | c6510a29e6b12a06fe9109990f2a895b05f3b112 (patch) | |
tree | 9d325ad51a69012512100b59749ce97d61f0f4c9 /alacritty/src/input.rs | |
parent | e8ca1ef7d988de9909a375680b1e081cae926341 (diff) | |
download | r-alacritty-c6510a29e6b12a06fe9109990f2a895b05f3b112.tar.gz r-alacritty-c6510a29e6b12a06fe9109990f2a895b05f3b112.tar.bz2 r-alacritty-c6510a29e6b12a06fe9109990f2a895b05f3b112.zip |
Fix modifier inconsistencies
Fixes #2906.
Diffstat (limited to 'alacritty/src/input.rs')
-rw-r--r-- | alacritty/src/input.rs | 182 |
1 files changed, 63 insertions, 119 deletions
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 5a852662..2a98dc12 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -26,7 +26,6 @@ use std::time::Instant; use glutin::event::{ ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase, - VirtualKeyCode, }; use glutin::window::CursorIcon; use log::{debug, trace, warn}; @@ -77,7 +76,7 @@ pub trait ActionContext<T: EventListener> { 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 Modifiers; + fn modifiers(&mut self) -> &mut ModifiersState; fn scroll(&mut self, scroll: Scroll); fn window(&self) -> &Window; fn window_mut(&mut self) -> &mut Window; @@ -91,64 +90,6 @@ pub trait ActionContext<T: EventListener> { fn config(&self) -> &Config; } -#[derive(Debug, Default, Copy, Clone)] -pub struct Modifiers { - glutin_mods: ModifiersState, - lshift: bool, - rshift: bool, - lalt: bool, - ralt: bool, - lctrl: bool, - rctrl: bool, -} - -impl Modifiers { - pub fn update_keys(&mut self, input: KeyboardInput) { - match input.virtual_keycode { - Some(VirtualKeyCode::LShift) => self.lshift = input.state == ElementState::Pressed, - Some(VirtualKeyCode::RShift) => self.rshift = input.state == ElementState::Pressed, - Some(VirtualKeyCode::LAlt) => self.lalt = input.state == ElementState::Pressed, - Some(VirtualKeyCode::RAlt) => self.ralt = input.state == ElementState::Pressed, - Some(VirtualKeyCode::LControl) => self.lctrl = input.state == ElementState::Pressed, - Some(VirtualKeyCode::RControl) => self.rctrl = input.state == ElementState::Pressed, - _ => (), - } - - self.update_mods(input.modifiers); - } - - pub fn update_mods(&mut self, mods: ModifiersState) { - self.glutin_mods = mods; - } - - pub fn shift(self) -> bool { - self.glutin_mods.shift || self.lshift || self.rshift - } - - pub fn ctrl(self) -> bool { - self.glutin_mods.ctrl || self.lctrl || self.rctrl - } - - pub fn logo(self) -> bool { - self.glutin_mods.logo - } - - pub fn alt(self) -> bool { - self.glutin_mods.alt || self.lalt || self.ralt - } -} - -impl From<Modifiers> for ModifiersState { - fn from(mods: Modifiers) -> ModifiersState { - ModifiersState { - shift: mods.shift(), - ctrl: mods.ctrl(), - logo: mods.logo(), - alt: mods.alt(), - } - } -} - trait Execute<T: EventListener> { fn execute<A: ActionContext<T>>(&self, ctx: &mut A, mouse_mode: bool); } @@ -254,39 +195,8 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { Self { ctx, urls, highlighted_url, _phantom: Default::default() } } - fn mouse_state(&mut self, mods: ModifiersState) -> MouseState { - // Check message bar before URL to ignore URLs in the message bar - if self.message_close_at_cursor() { - return MouseState::MessageBarButton; - } else if self.message_at_cursor() { - return MouseState::MessageBar; - } - - // Check for URL at mouse cursor - let selection = - !self.ctx.terminal().selection().as_ref().map(Selection::is_empty).unwrap_or(true); - let mouse_mode = self.ctx.terminal().mode().intersects(TermMode::MOUSE_MODE); - let highlighted_url = - self.urls.highlighted(self.ctx.config(), self.ctx.mouse(), mods, mouse_mode, selection); - - if let Some(url) = highlighted_url { - return MouseState::Url(url); - } - - // Check mouse mode if location is not special - if self.ctx.terminal().mode().intersects(TermMode::MOUSE_MODE) - && !self.ctx.modifiers().shift() - { - MouseState::Mouse - } else { - MouseState::Text - } - } - #[inline] pub fn mouse_moved(&mut self, x: usize, y: usize, modifiers: ModifiersState) { - self.ctx.modifiers().update_mods(modifiers); - let size_info = self.ctx.size_info(); self.ctx.mouse_mut().x = x; @@ -366,7 +276,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } } - pub fn normal_mouse_report(&mut self, button: u8) { + fn normal_mouse_report(&mut self, button: u8) { let (line, column) = (self.ctx.mouse().line, self.ctx.mouse().column); let utf8 = self.ctx.terminal().mode().contains(TermMode::UTF8_MOUSE); @@ -400,7 +310,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { self.ctx.write_to_pty(msg); } - pub fn sgr_mouse_report(&mut self, button: u8, state: ElementState) { + fn sgr_mouse_report(&mut self, button: u8, state: ElementState) { let (line, column) = (self.ctx.mouse().line, self.ctx.mouse().column); let c = match state { ElementState::Pressed => 'M', @@ -411,7 +321,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { self.ctx.write_to_pty(msg.into_bytes()); } - pub fn mouse_report(&mut self, button: u8, state: ElementState, modifiers: ModifiersState) { + fn mouse_report(&mut self, button: u8, state: ElementState, modifiers: ModifiersState) { // Calculate modifiers value let mut mods = 0; if modifiers.shift { @@ -434,21 +344,19 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } } - pub fn on_mouse_double_click(&mut self, button: MouseButton, point: Point) { + fn on_mouse_double_click(&mut self, button: MouseButton, point: Point) { if button == MouseButton::Left { self.ctx.semantic_selection(point); } } - pub fn on_mouse_triple_click(&mut self, button: MouseButton, point: Point) { + fn on_mouse_triple_click(&mut self, button: MouseButton, point: Point) { if button == MouseButton::Left { self.ctx.line_selection(point); } } - pub fn on_mouse_press(&mut self, button: MouseButton, modifiers: ModifiersState) { - self.ctx.modifiers().update_mods(modifiers); - + fn on_mouse_press(&mut self, button: MouseButton, modifiers: ModifiersState) { let now = Instant::now(); let elapsed = self.ctx.mouse().last_click_timestamp.elapsed(); self.ctx.mouse_mut().last_click_timestamp = now; @@ -508,7 +416,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { }; } - pub fn on_mouse_release(&mut self, button: MouseButton, modifiers: ModifiersState) { + fn on_mouse_release(&mut self, button: MouseButton, modifiers: ModifiersState) { if !modifiers.shift && self.ctx.terminal().mode().intersects(TermMode::MOUSE_MODE) { let code = match button { MouseButton::Left => 0, @@ -547,7 +455,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } } - pub fn on_mouse_wheel( + pub fn mouse_wheel_input( &mut self, delta: MouseScrollDelta, phase: TouchPhase, @@ -683,14 +591,9 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } /// Process key input. - pub fn process_key(&mut self, input: KeyboardInput) { - self.ctx.modifiers().update_keys(input); - - // Update mouse state and check for URL change - let mods = (*self.ctx.modifiers()).into(); - let mouse_state = self.mouse_state(mods); - self.update_url_state(&mouse_state); - self.ctx.window_mut().set_mouse_cursor(mouse_state.into()); + pub fn key_input(&mut self, input: KeyboardInput) { + // TODO: Implement `ModifiersChanged` event on all platforms: rust-windowing/winit#1151 + self.modifiers_input(input.modifiers); match input.state { ElementState::Pressed => { @@ -701,6 +604,16 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } } + /// Modifier state change. + pub fn modifiers_input(&mut self, modifiers: ModifiersState) { + *self.ctx.modifiers() = modifiers; + + // Update mouse state and check for URL change + let mouse_state = self.mouse_state(modifiers); + self.update_url_state(&mouse_state); + self.ctx.window_mut().set_mouse_cursor(mouse_state.into()); + } + /// Process a received character. pub fn received_char(&mut self, c: char) { if *self.ctx.suppress_chars() { @@ -719,7 +632,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { if self.ctx.config().alt_send_esc() && *self.ctx.received_count() == 0 - && self.ctx.modifiers().alt() + && self.ctx.modifiers().alt && utf8_len == 1 { bytes.insert(0, b'\x1b'); @@ -731,6 +644,14 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { self.ctx.terminal_mut().dirty = false; } + /// Reset mouse cursor based on modifier and terminal state. + #[inline] + pub fn reset_mouse_cursor(&mut self) { + let mods = *self.ctx.modifiers(); + let mouse_state = self.mouse_state(mods); + self.ctx.window_mut().set_mouse_cursor(mouse_state.into()); + } + /// Attempt to find a binding and execute its action. /// /// The provided mode, mods, and key must match what is allowed by a binding @@ -813,11 +734,34 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { } } - #[inline] - pub fn reset_mouse_cursor(&mut self) { - let mods = (*self.ctx.modifiers()).into(); - let mouse_state = self.mouse_state(mods); - self.ctx.window_mut().set_mouse_cursor(mouse_state.into()); + /// Location of the mouse cursor. + fn mouse_state(&mut self, mods: ModifiersState) -> MouseState { + // Check message bar before URL to ignore URLs in the message bar + if self.message_close_at_cursor() { + return MouseState::MessageBarButton; + } else if self.message_at_cursor() { + return MouseState::MessageBar; + } + + // Check for URL at mouse cursor + let selection = + !self.ctx.terminal().selection().as_ref().map(Selection::is_empty).unwrap_or(true); + let mouse_mode = self.ctx.terminal().mode().intersects(TermMode::MOUSE_MODE); + let highlighted_url = + self.urls.highlighted(self.ctx.config(), self.ctx.mouse(), mods, mouse_mode, selection); + + if let Some(url) = highlighted_url { + return MouseState::Url(url); + } + + // Check mouse mode if location is not special + if self.ctx.terminal().mode().intersects(TermMode::MOUSE_MODE) + && !self.ctx.modifiers().shift + { + MouseState::Mouse + } else { + MouseState::Text + } } } @@ -843,7 +787,7 @@ mod tests { use crate::url::Urls; use crate::window::Window; - use super::{Action, Binding, Modifiers, Processor}; + use super::{Action, Binding, Processor}; const KEY: VirtualKeyCode = VirtualKeyCode::Key0; @@ -869,7 +813,7 @@ mod tests { pub last_action: MultiClick, pub received_count: usize, pub suppress_chars: bool, - pub modifiers: Modifiers, + pub modifiers: ModifiersState, config: &'a Config, } @@ -950,7 +894,7 @@ mod tests { &mut self.suppress_chars } - fn modifiers(&mut self) -> &mut Modifiers { + fn modifiers(&mut self) -> &mut ModifiersState { &mut self.modifiers } @@ -1026,7 +970,7 @@ mod tests { last_action: MultiClick::None, received_count: 0, suppress_chars: false, - modifiers: Modifiers::default(), + modifiers: Default::default(), message_buffer: &mut message_buffer, config: &cfg, }; |