aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2017-01-01 18:28:49 -0800
committerJoe Wilm <joe@jwilm.com>2017-01-01 18:28:49 -0800
commit82bfc41af7d6eff384bdf95cedaf0d62b5450979 (patch)
treed49059a741b4d751d424f15cf3d33cd8042aaa14
parenta86dfd1a113f62fb6c40ebf5fe80f30a60cdff99 (diff)
downloadalacritty-82bfc41af7d6eff384bdf95cedaf0d62b5450979.tar.gz
alacritty-82bfc41af7d6eff384bdf95cedaf0d62b5450979.zip
Add support for SGR mouse reporting
According to: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
-rw-r--r--src/ansi.rs6
-rw-r--r--src/index.rs4
-rw-r--r--src/input.rs66
-rw-r--r--src/term/mod.rs6
4 files changed, 57 insertions, 25 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index 633a7e54..e5c129e3 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -249,6 +249,10 @@ pub enum Mode {
ShowCursor = 25,
/// ?1000
ReportMouseClicks = 1000,
+ /// ?1002
+ ReportMouseMotion = 1002,
+ /// ?1006
+ SgrMouse = 1006,
/// ?1049
SwapScreenAndSetRestoreCursor = 1049,
/// ?2004
@@ -267,6 +271,8 @@ impl Mode {
12 => Mode::BlinkingCursor,
25 => Mode::ShowCursor,
1000 => Mode::ReportMouseClicks,
+ 1002 => Mode::ReportMouseMotion,
+ 1006 => Mode::SgrMouse,
1049 => Mode::SwapScreenAndSetRestoreCursor,
2004 => Mode::BracketedPaste,
_ => return None
diff --git a/src/index.rs b/src/index.rs
index 7cb6ee24..c80589da 100644
--- a/src/index.rs
+++ b/src/index.rs
@@ -62,7 +62,7 @@ pub struct Line(pub usize);
impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Line({})", self.0)
+ write!(f, "{}", self.0)
}
}
@@ -74,7 +74,7 @@ pub struct Column(pub usize);
impl fmt::Display for Column {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Column({})", self.0)
+ write!(f, "{}", self.0)
}
}
diff --git a/src/input.rs b/src/input.rs
index 60183098..960bc017 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -18,11 +18,8 @@
//! In order to figure that out, state about which modifier keys are pressed
//! needs to be tracked. Additionally, we need a bit of a state machine to
//! determine what to do when a non-modifier key is pressed.
-//!
-//! TODO would be nice to generalize this so it could work with other windowing
-//! APIs
-//!
-//! TODO handling xmodmap would be good
+use std::mem;
+
use copypasta::{Clipboard, Load, Store};
use glutin::{ElementState, VirtualKeyCode, MouseButton};
use glutin::{Mods, mods};
@@ -188,15 +185,12 @@ impl From<&'static str> for Action {
impl<'a, N: Notify + 'a> Processor<'a, N> {
#[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.ctx.mouse.x = x;
self.ctx.mouse.y = y;
if let Some(point) = self.ctx.size_info.pixels_to_coords(x as usize, y as usize) {
- self.ctx.mouse.line = point.line;
- self.ctx.mouse.column = point.col;
+ let prev_line = mem::replace(&mut self.ctx.mouse.line, point.line);
+ let prev_col = mem::replace(&mut self.ctx.mouse.column, point.col);
let cell_x = x as usize % self.ctx.size_info.cell_width as usize;
let half_cell_width = (self.ctx.size_info.cell_width / 2.0) as usize;
@@ -207,18 +201,28 @@ impl<'a, N: Notify + 'a> Processor<'a, N> {
Side::Left
};
- if self.ctx.mouse.left_button_state == ElementState::Pressed &&
- !self.ctx.terminal.mode().contains(mode::MOUSE_REPORT_CLICK)
- {
- self.ctx.selection.update(Point {
- line: point.line,
- col: point.col
- }, self.ctx.mouse.cell_side);
+ if self.ctx.mouse.left_button_state == ElementState::Pressed {
+ let report_mode = mode::MOUSE_REPORT_CLICK | mode::MOUSE_MOTION;
+ if !self.ctx.terminal.mode().intersects(report_mode) {
+ self.ctx.selection.update(Point {
+ line: point.line,
+ col: point.col
+ }, self.ctx.mouse.cell_side);
+ } else if self.ctx.terminal.mode().contains(mode::MOUSE_MOTION) {
+ // Only report motion when changing cells
+ if prev_line != self.ctx.mouse.line || prev_col != self.ctx.mouse.column {
+ self.mouse_report(0 + 32);
+ }
+ }
}
}
}
- pub fn mouse_report(&mut self, button: u8) {
+ pub fn mouse_moved_cells(&mut self) {
+
+ }
+
+ pub fn normal_mouse_report(&mut self, button: u8) {
let (line, column) = (self.ctx.mouse.line, self.ctx.mouse.column);
if line < Line(223) && column < Column(223) {
@@ -235,8 +239,25 @@ impl<'a, N: Notify + 'a> Processor<'a, N> {
}
}
+ pub fn sgr_mouse_report(&mut self, button: u8, release: bool) {
+ let (line, column) = (self.ctx.mouse.line, self.ctx.mouse.column);
+ let c = if release { 'm' } else { 'M' };
+
+ let msg = format!("\x1b[<{};{};{}{}", button, column + 1, line + 1, c);
+ self.ctx.notifier.notify(msg.into_bytes());
+ }
+
+ pub fn mouse_report(&mut self, button: u8) {
+ if self.ctx.terminal.mode().contains(mode::SGR_MOUSE) {
+ let release = self.ctx.mouse.left_button_state != ElementState::Pressed;
+ self.sgr_mouse_report(button, release);
+ } else {
+ self.normal_mouse_report(button);
+ }
+ }
+
pub fn on_mouse_press(&mut self) {
- if self.ctx.terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
+ if self.ctx.terminal.mode().intersects(mode::MOUSE_REPORT_CLICK | mode::MOUSE_MOTION) {
self.mouse_report(0);
return;
}
@@ -245,7 +266,7 @@ impl<'a, N: Notify + 'a> Processor<'a, N> {
}
pub fn on_mouse_release(&mut self) {
- if self.ctx.terminal.mode().contains(mode::MOUSE_REPORT_CLICK) {
+ if self.ctx.terminal.mode().intersects(mode::MOUSE_REPORT_CLICK | mode::MOUSE_MOTION) {
self.mouse_report(3);
return;
}
@@ -304,10 +325,9 @@ impl<'a, N: Notify + 'a> Processor<'a, N> {
pub fn mouse_input(&mut self, state: ElementState, button: MouseButton) {
if let MouseButton::Left = button {
- // TODO handle state changes
+ let state = mem::replace(&mut self.ctx.mouse.left_button_state, state);
if self.ctx.mouse.left_button_state != state {
- self.ctx.mouse.left_button_state = state;
- match state {
+ match self.ctx.mouse.left_button_state {
ElementState::Pressed => {
self.on_mouse_press();
},
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 319f7520..c93ec963 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -180,6 +180,8 @@ pub mod mode {
const APP_KEYPAD = 0b00000100,
const MOUSE_REPORT_CLICK = 0b00001000,
const BRACKETED_PASTE = 0b00010000,
+ const SGR_MOUSE = 0b00100000,
+ const MOUSE_MOTION = 0b01000000,
const ANY = 0b11111111,
const NONE = 0b00000000,
}
@@ -987,7 +989,9 @@ impl ansi::Handler for Term {
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),
+ ansi::Mode::ReportMouseMotion => self.mode.insert(mode::MOUSE_MOTION),
ansi::Mode::BracketedPaste => self.mode.insert(mode::BRACKETED_PASTE),
+ ansi::Mode::SgrMouse => self.mode.insert(mode::SGR_MOUSE),
_ => {
debug_println!(".. ignoring set_mode");
}
@@ -1002,7 +1006,9 @@ impl ansi::Handler for Term {
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),
+ ansi::Mode::ReportMouseMotion => self.mode.remove(mode::MOUSE_MOTION),
ansi::Mode::BracketedPaste => self.mode.remove(mode::BRACKETED_PASTE),
+ ansi::Mode::SgrMouse => self.mode.remove(mode::SGR_MOUSE),
_ => {
debug_println!(".. ignoring unset_mode");
}