aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-11-23 20:25:37 -0800
committerJoe Wilm <joe@jwilm.com>2016-12-11 20:23:41 -0800
commit90e0a759e8e55952ada459914f9958d50eab04fe (patch)
tree58fde9affe7e8516481d5983afd9186f620e6ffa /src
parentb6c372ab4800b8dbc9e3efb042e369c9980c607a (diff)
downloadalacritty-90e0a759e8e55952ada459914f9958d50eab04fe.tar.gz
alacritty-90e0a759e8e55952ada459914f9958d50eab04fe.zip
Support normal mouse tracking mode
This allows the user for eg clicking columnts in htop to sort.
Diffstat (limited to 'src')
-rw-r--r--src/ansi.rs3
-rw-r--r--src/event.rs7
-rw-r--r--src/input.rs87
-rw-r--r--src/term.rs31
4 files changed, 119 insertions, 9 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index eaa34430..c9341620 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -239,6 +239,8 @@ pub enum Mode {
BlinkingCursor = 12,
/// ?25
ShowCursor = 25,
+ /// ?1000
+ ReportMouseClicks = 1000,
/// ?1049
SwapScreenAndSetRestoreCursor = 1049,
}
@@ -254,6 +256,7 @@ impl Mode {
6 => Mode::Origin,
12 => Mode::BlinkingCursor,
25 => Mode::ShowCursor,
+ 1000 => Mode::ReportMouseClicks,
1049 => Mode::SwapScreenAndSetRestoreCursor,
_ => return None
})
diff --git a/src/event.rs b/src/event.rs
index 5ec156c3..b220ae2c 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -86,7 +86,12 @@ impl<N: input::Notify> Processor<N> {
let processor = &mut self.input_processor;
let notifier = &mut self.notifier;
- processor.mouse_input(state, button, notifier, *terminal.mode());
+ processor.mouse_input(state, button, notifier, &terminal);
+ },
+ glutin::Event::MouseMoved(x, y) => {
+ if x > 0 && y > 0 {
+ self.input_processor.mouse_moved(x as u32, y as u32);
+ }
},
glutin::Event::Focused(true) => {
let mut terminal = self.terminal.lock();
diff --git a/src/input.rs b/src/input.rs
index 9d70e772..2e90ee20 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -29,9 +29,11 @@ use copypasta::{Clipboard, Load};
use glutin::{ElementState, VirtualKeyCode, MouseButton};
use glutin::{Mods, mods};
+use index::{Line, Column};
use config::Config;
use event_loop;
-use term::mode::{TermMode};
+use term::mode::{self, TermMode};
+use term::Term;
/// Processes input from glutin.
///
@@ -43,6 +45,24 @@ use term::mode::{TermMode};
pub struct Processor {
key_bindings: Vec<KeyBinding>,
mouse_bindings: Vec<MouseBinding>,
+ mouse: Mouse,
+}
+
+/// State of the mouse
+pub struct Mouse {
+ x: u32,
+ y: u32,
+ left_button_state: ElementState,
+}
+
+impl Default for Mouse {
+ fn default() -> Mouse {
+ Mouse {
+ x: 0,
+ y: 0,
+ left_button_state: ElementState::Pressed
+ }
+ }
}
/// Types that are notified of escape sequences from the input::Processor.
@@ -219,23 +239,84 @@ impl Processor {
Processor {
key_bindings: config.key_bindings().to_vec(),
mouse_bindings: config.mouse_bindings().to_vec(),
+ mouse: Mouse::default(),
+ }
+ }
+
+ #[inline]
+ pub fn mouse_moved(&mut self, x: u32, y: u32) {
+ // Record mouse position within window. Pixel coordinates are *not*
+ // translated to grid coordinates here since grid coordinates are rarely
+ // needed and the mouse position updates frequently.
+ self.mouse.x = x;
+ self.mouse.y = y;
+ }
+
+ fn mouse_report<N: Notify>(
+ &mut self,
+ button: u8,
+ notifier: &mut N,
+ terminal: &Term
+ ) {
+ if terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
+ let (line, column) = terminal.pixels_to_coords(
+ self.mouse.x as usize,
+ self.mouse.y as usize
+ ).unwrap();
+
+ if line < Line(223) && column < Column(223) {
+ let msg = vec![
+ '\x1b' as u8,
+ '[' as u8,
+ 'M' as u8,
+ 32 + button,
+ 32 + 1 + column.0 as u8,
+ 32 + 1 + line.0 as u8,
+ ];
+
+ notifier.notify(msg);
+ }
+
}
}
+ pub fn on_mouse_press<N: Notify>(&mut self, notifier: &mut N, terminal: &Term) {
+ self.mouse_report(0, notifier, terminal);
+ }
+
+ pub fn on_mouse_release<N: Notify>(&mut self, notifier: &mut N, terminal: &Term) {
+ self.mouse_report(3, notifier, terminal);
+ }
+
pub fn mouse_input<N: Notify>(
&mut self,
state: ElementState,
button: MouseButton,
notifier: &mut N,
- mode: TermMode
+ terminal: &Term
) {
+ if let MouseButton::Left = button {
+ // TODO handle state changes
+ if self.mouse.left_button_state != state {
+ self.mouse.left_button_state = state;
+ match state {
+ ElementState::Pressed => {
+ self.on_mouse_press(notifier, terminal);
+ },
+ ElementState::Released => {
+ self.on_mouse_release(notifier, terminal);
+ }
+ }
+ }
+ }
+
if let ElementState::Released = state {
return;
}
Processor::process_mouse_bindings(
&self.mouse_bindings[..],
- mode,
+ *terminal.mode(),
notifier,
mods::NONE,
button
diff --git a/src/term.rs b/src/term.rs
index 33890ad5..d2d711b4 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -162,11 +162,12 @@ pub use self::cell::Cell;
pub mod mode {
bitflags! {
pub flags TermMode: u8 {
- const SHOW_CURSOR = 0b00000001,
- const APP_CURSOR = 0b00000010,
- const APP_KEYPAD = 0b00000100,
- const ANY = 0b11111111,
- const NONE = 0b00000000,
+ const SHOW_CURSOR = 0b00000001,
+ const APP_CURSOR = 0b00000010,
+ const APP_KEYPAD = 0b00000100,
+ const MOUSE_REPORT_CLICK = 0b00001000,
+ const ANY = 0b11111111,
+ const NONE = 0b00000000,
}
}
@@ -288,6 +289,24 @@ impl Term {
}
}
+ /// Convert the given pixel values to a grid coordinate
+ ///
+ /// The mouse coordinates are expected to be relative to the top left. The
+ /// line and column returned are also relative to the top left.
+ ///
+ /// 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))
+ }
+
pub fn grid(&self) -> &Grid<Cell> {
&self.grid
}
@@ -815,6 +834,7 @@ impl ansi::Handler for Term {
ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(),
ansi::Mode::ShowCursor => self.mode.insert(mode::SHOW_CURSOR),
ansi::Mode::CursorKeys => self.mode.insert(mode::APP_CURSOR),
+ ansi::Mode::ReportMouseClicks => self.mode.insert(mode::MOUSE_REPORT_CLICK),
_ => {
debug_println!(".. ignoring set_mode");
}
@@ -828,6 +848,7 @@ impl ansi::Handler for Term {
ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(),
ansi::Mode::ShowCursor => self.mode.remove(mode::SHOW_CURSOR),
ansi::Mode::CursorKeys => self.mode.remove(mode::APP_CURSOR),
+ ansi::Mode::ReportMouseClicks => self.mode.remove(mode::MOUSE_REPORT_CLICK),
_ => {
debug_println!(".. ignoring unset_mode");
}