mirror of
https://github.com/alacritty/alacritty.git
synced 2025-04-14 17:53:03 -04: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,
|
||||
/// ?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
|
||||
})
|
||||
|
|
|
@ -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();
|
||||
|
|
87
src/input.rs
87
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
|
||||
|
|
31
src/term.rs
31
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");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue