aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-12-11 22:02:03 -0800
committerJoe Wilm <joe@jwilm.com>2016-12-11 22:02:03 -0800
commit4b63bddd55853e878ec0f85b4613dd02749a3811 (patch)
tree02faaf58b29e3e8c5767bca1c2254376d2f47fb6 /src
parent79e02b0b2f2feb127ff1c7dc998d4696e005003a (diff)
downloadalacritty-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.rs24
-rw-r--r--src/input.rs27
-rw-r--r--src/main.rs41
-rw-r--r--src/term/mod.rs21
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