mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-11 13:51:01 -05:00
Support normal mouse tracking mode
This allows the user for eg clicking columnts in htop to sort.
This commit is contained in:
parent
b6c372ab48
commit
90e0a759e8
4 changed files with 119 additions and 9 deletions
|
@ -239,6 +239,8 @@ pub enum Mode {
|
||||||
BlinkingCursor = 12,
|
BlinkingCursor = 12,
|
||||||
/// ?25
|
/// ?25
|
||||||
ShowCursor = 25,
|
ShowCursor = 25,
|
||||||
|
/// ?1000
|
||||||
|
ReportMouseClicks = 1000,
|
||||||
/// ?1049
|
/// ?1049
|
||||||
SwapScreenAndSetRestoreCursor = 1049,
|
SwapScreenAndSetRestoreCursor = 1049,
|
||||||
}
|
}
|
||||||
|
@ -254,6 +256,7 @@ impl Mode {
|
||||||
6 => Mode::Origin,
|
6 => Mode::Origin,
|
||||||
12 => Mode::BlinkingCursor,
|
12 => Mode::BlinkingCursor,
|
||||||
25 => Mode::ShowCursor,
|
25 => Mode::ShowCursor,
|
||||||
|
1000 => Mode::ReportMouseClicks,
|
||||||
1049 => Mode::SwapScreenAndSetRestoreCursor,
|
1049 => Mode::SwapScreenAndSetRestoreCursor,
|
||||||
_ => return None
|
_ => return None
|
||||||
})
|
})
|
||||||
|
|
|
@ -86,7 +86,12 @@ impl<N: input::Notify> Processor<N> {
|
||||||
let processor = &mut self.input_processor;
|
let processor = &mut self.input_processor;
|
||||||
let notifier = &mut self.notifier;
|
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) => {
|
glutin::Event::Focused(true) => {
|
||||||
let mut terminal = self.terminal.lock();
|
let mut terminal = self.terminal.lock();
|
||||||
|
|
87
src/input.rs
87
src/input.rs
|
@ -29,9 +29,11 @@ use copypasta::{Clipboard, Load};
|
||||||
use glutin::{ElementState, VirtualKeyCode, MouseButton};
|
use glutin::{ElementState, VirtualKeyCode, MouseButton};
|
||||||
use glutin::{Mods, mods};
|
use glutin::{Mods, mods};
|
||||||
|
|
||||||
|
use index::{Line, Column};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use event_loop;
|
use event_loop;
|
||||||
use term::mode::{TermMode};
|
use term::mode::{self, TermMode};
|
||||||
|
use term::Term;
|
||||||
|
|
||||||
/// Processes input from glutin.
|
/// Processes input from glutin.
|
||||||
///
|
///
|
||||||
|
@ -43,6 +45,24 @@ use term::mode::{TermMode};
|
||||||
pub struct Processor {
|
pub struct Processor {
|
||||||
key_bindings: Vec<KeyBinding>,
|
key_bindings: Vec<KeyBinding>,
|
||||||
mouse_bindings: Vec<MouseBinding>,
|
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.
|
/// Types that are notified of escape sequences from the input::Processor.
|
||||||
|
@ -219,23 +239,84 @@ impl Processor {
|
||||||
Processor {
|
Processor {
|
||||||
key_bindings: config.key_bindings().to_vec(),
|
key_bindings: config.key_bindings().to_vec(),
|
||||||
mouse_bindings: config.mouse_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>(
|
pub fn mouse_input<N: Notify>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: ElementState,
|
state: ElementState,
|
||||||
button: MouseButton,
|
button: MouseButton,
|
||||||
notifier: &mut N,
|
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 {
|
if let ElementState::Released = state {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Processor::process_mouse_bindings(
|
Processor::process_mouse_bindings(
|
||||||
&self.mouse_bindings[..],
|
&self.mouse_bindings[..],
|
||||||
mode,
|
*terminal.mode(),
|
||||||
notifier,
|
notifier,
|
||||||
mods::NONE,
|
mods::NONE,
|
||||||
button
|
button
|
||||||
|
|
21
src/term.rs
21
src/term.rs
|
@ -165,6 +165,7 @@ pub mod mode {
|
||||||
const SHOW_CURSOR = 0b00000001,
|
const SHOW_CURSOR = 0b00000001,
|
||||||
const APP_CURSOR = 0b00000010,
|
const APP_CURSOR = 0b00000010,
|
||||||
const APP_KEYPAD = 0b00000100,
|
const APP_KEYPAD = 0b00000100,
|
||||||
|
const MOUSE_REPORT_CLICK = 0b00001000,
|
||||||
const ANY = 0b11111111,
|
const ANY = 0b11111111,
|
||||||
const NONE = 0b00000000,
|
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> {
|
pub fn grid(&self) -> &Grid<Cell> {
|
||||||
&self.grid
|
&self.grid
|
||||||
}
|
}
|
||||||
|
@ -815,6 +834,7 @@ impl ansi::Handler for Term {
|
||||||
ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(),
|
ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(),
|
||||||
ansi::Mode::ShowCursor => self.mode.insert(mode::SHOW_CURSOR),
|
ansi::Mode::ShowCursor => self.mode.insert(mode::SHOW_CURSOR),
|
||||||
ansi::Mode::CursorKeys => self.mode.insert(mode::APP_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");
|
debug_println!(".. ignoring set_mode");
|
||||||
}
|
}
|
||||||
|
@ -828,6 +848,7 @@ impl ansi::Handler for Term {
|
||||||
ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(),
|
ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(),
|
||||||
ansi::Mode::ShowCursor => self.mode.remove(mode::SHOW_CURSOR),
|
ansi::Mode::ShowCursor => self.mode.remove(mode::SHOW_CURSOR),
|
||||||
ansi::Mode::CursorKeys => self.mode.remove(mode::APP_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");
|
debug_println!(".. ignoring unset_mode");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue