diff options
author | Joe Wilm <joe@jwilm.com> | 2016-12-11 22:02:03 -0800 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-12-11 22:02:03 -0800 |
commit | 4b63bddd55853e878ec0f85b4613dd02749a3811 (patch) | |
tree | 02faaf58b29e3e8c5767bca1c2254376d2f47fb6 /src | |
parent | 79e02b0b2f2feb127ff1c7dc998d4696e005003a (diff) | |
download | alacritty-4b63bddd55853e878ec0f85b4613dd02749a3811.tar.gz alacritty-4b63bddd55853e878ec0f85b4613dd02749a3811.zip |
Track terminal cells on mouse movement
The cell under the cursor is now tracked in the input processor at
`self.mouse.line` and `self.mouse.column`. This could probably be
optimized to only compute the cell when in certain states, but the
calculation is cheap.
Diffstat (limited to 'src')
-rw-r--r-- | src/event.rs | 24 | ||||
-rw-r--r-- | src/input.rs | 27 | ||||
-rw-r--r-- | src/main.rs | 41 | ||||
-rw-r--r-- | src/term/mod.rs | 21 |
4 files changed, 77 insertions, 36 deletions
diff --git a/src/event.rs b/src/event.rs index d8fec37e..4f28649e 100644 --- a/src/event.rs +++ b/src/event.rs @@ -10,7 +10,7 @@ use window::Window; use input; use sync::FairMutex; -use term::Term; +use term::{self, Term}; use config::Config; /// The event processor @@ -34,15 +34,27 @@ impl<N: input::Notify> Processor<N> { config: &Config, ref_test: bool, ) -> Processor<N> { + let input_processor = { + let terminal = terminal.lock(); + input::Processor::new(config, terminal.size_info()) + }; + Processor { notifier: notifier, terminal: terminal, - input_processor: input::Processor::new(config), + input_processor: input_processor, resize_tx: resize_tx, ref_test: ref_test, } } + /// Notify that the terminal was resized + /// + /// Currently this just forwards the notice to the input processor. + pub fn resize(&mut self, size_info: &term::SizeInfo) { + self.input_processor.resize(size_info); + } + fn handle_event(&mut self, event: glutin::Event, wakeup_request: &mut bool) { match event { glutin::Event::Closed => { @@ -71,9 +83,11 @@ impl<N: input::Notify> Processor<N> { }, glutin::Event::Resized(w, h) => { self.resize_tx.send((w, h)).expect("send new size"); - // Acquire term lock - let mut terminal = self.terminal.lock(); - terminal.dirty = true; + + // Previously, this marked the terminal state as "dirty", but + // now the wakeup_request controls whether a display update is + // triggered. + *wakeup_request = true; }, glutin::Event::KeyboardInput(state, _code, key, mods, string) => { // Acquire term lock diff --git a/src/input.rs b/src/input.rs index 994b2f1b..0aa3a738 100644 --- a/src/input.rs +++ b/src/input.rs @@ -24,17 +24,19 @@ //! //! TODO handling xmodmap would be good use std::borrow::Cow; +use std::mem; use copypasta::{Clipboard, Load}; use glutin::{ElementState, VirtualKeyCode, MouseButton}; use glutin::{Mods, mods}; use glutin::{TouchPhase, MouseScrollDelta}; -use index::{Line, Column}; use config::Config; use event_loop; +use index::{Line, Column}; +use sync::FairMutex; use term::mode::{self, TermMode}; -use term::Term; +use term::{self, Term}; /// Processes input from glutin. /// @@ -42,11 +44,11 @@ use term::Term; /// are activated. /// /// TODO also need terminal state when processing input -#[derive(Default)] pub struct Processor { key_bindings: Vec<KeyBinding>, mouse_bindings: Vec<MouseBinding>, mouse: Mouse, + size_info: term::SizeInfo, } /// State of the mouse @@ -55,6 +57,8 @@ pub struct Mouse { y: u32, left_button_state: ElementState, scroll_px: i32, + line: Line, + column: Column, } impl Default for Mouse { @@ -64,6 +68,8 @@ impl Default for Mouse { y: 0, left_button_state: ElementState::Pressed, scroll_px: 0, + line: Line(0), + column: Column(0), } } } @@ -244,11 +250,16 @@ impl Binding { // crlf = LNM (Linefeed/new line); wtf is this impl Processor { - pub fn new(config: &Config) -> Processor { + pub fn resize(&mut self, size_info: &term::SizeInfo) { + self.size_info = size_info.to_owned(); + } + + pub fn new(config: &Config, size_info: &term::SizeInfo) -> Processor { Processor { key_bindings: config.key_bindings().to_vec(), mouse_bindings: config.mouse_bindings().to_vec(), mouse: Mouse::default(), + size_info: size_info.to_owned(), } } @@ -259,9 +270,15 @@ impl Processor { // needed and the mouse position updates frequently. self.mouse.x = x; self.mouse.y = y; + + if let Some((line, column)) = self.size_info.pixels_to_coords(x as usize, y as usize) { + // Swap values for following comparison + let line = mem::replace(&mut self.mouse.line, line); + let column = mem::replace(&mut self.mouse.column, column); + } } - fn mouse_report<N: Notify>( + pub fn mouse_report<N: Notify>( &mut self, button: u8, notifier: &mut N, diff --git a/src/main.rs b/src/main.rs index d4194c28..7ae45787 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,9 +18,10 @@ #[macro_use] extern crate alacritty; +use std::cell::RefCell; use std::error::Error; -use std::sync::Arc; use std::rc::Rc; +use std::sync::Arc; use alacritty::cli; use alacritty::config::{self, Config}; @@ -85,18 +86,7 @@ fn run(config: Config, options: cli::Options) -> Result<(), Box<Error>> { // The pty forks a process to run the shell on the slave side of the // pseudoterminal. A file descriptor for the master side is retained for // reading/writing to the shell. - let pty = Rc::new(tty::new(display.size())); - - // When the display is resized, inform the kernel of changes to pty - // dimensions. - // - // TODO: The Rc on pty is needed due to a borrowck error here. The borrow - // checker says that `pty` is still borrowed when it is dropped at the end - // of the `run` function. - let pty_ref = pty.clone(); - display.set_resize_callback(move |size| { - pty_ref.resize(size); - }); + let pty = tty::new(display.size()); // Create the pseudoterminal I/O loop // @@ -116,13 +106,30 @@ fn run(config: Config, options: cli::Options) -> Result<(), Box<Error>> { let loop_tx = event_loop.channel(); // Event processor - let mut processor = event::Processor::new( + // + // Need the Rc<RefCell<_>> here since a ref is shared in the resize callback + let processor = Rc::new(RefCell::new(event::Processor::new( input::LoopNotifier(loop_tx), terminal.clone(), display.resize_channel(), &config, options.ref_test, - ); + ))); + + // Configure the display resize callback + let processor_ref = processor.clone(); + display.set_resize_callback(move |size| { + // Resizing the pty lets the child processes know the window changed + // size. + pty.resize(size); + + // It's a bit funny that the event processor is in this callback since + // on some platforms it's the first to be aware of a resize event. It + // appears here since resizes are processed out-of-band from when the + // events arrive. This way, the processor state is updated at the same + // time as the rest of the system. + processor_ref.borrow_mut().resize(size) + }); // Create a config monitor when config was loaded from path // @@ -137,14 +144,14 @@ fn run(config: Config, options: cli::Options) -> Result<(), Box<Error>> { // Main display loop loop { // Process input and window events - let wakeup_request = processor.process_events(display.window()); + let wakeup_request = processor.borrow_mut().process_events(display.window()); // Handle config reloads let config_updated = config_monitor.as_ref() .and_then(|monitor| monitor.pending_config()) .map(|config| { display.update_config(&config); - processor.update_config(&config); + processor.borrow_mut().update_config(&config); true }).unwrap_or(false); diff --git a/src/term/mod.rs b/src/term/mod.rs index da5683e0..523fcb62 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -259,6 +259,17 @@ impl SizeInfo { pub fn cols(&self) -> Column { Column((self.width / self.cell_width) as usize) } + + pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option<(Line, Column)> { + if x > self.width as usize || y > self.height as usize { + return None; + } + + let col = Column(x / (self.cell_width as usize)); + let line = Line(y / (self.cell_height as usize)); + + Some((line, col)) + } } impl Term { @@ -306,15 +317,7 @@ impl Term { /// /// Returns None if the coordinates are outside the screen pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option<(Line, Column)> { - let size = self.size_info(); - if x > size.width as usize || y > size.height as usize { - return None; - } - - let col = Column(x / (size.cell_width as usize)); - let line = Line(y / (size.cell_height as usize)); - - Some((line, col)) + self.size_info().pixels_to_coords(x, y) } /// Access to the raw grid data structure |