mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-25 14:05:41 -05:00
Change mouse cursor on terminal mode change (#865)
Some terminals have functionality around changing the type of mouse
cursor dynamically (arrow and text) based on which mode(s) the VTE is
in. For example, gnome-terminal changes the cursor from text (default)
to an arrow when opening programs that track mouse events (e.g. vim,
emacs, tmux, htop, etc.). The programs all allow using the mouse
interactively under some circumstances (like executing `set mouse=a` in
vim).
The programs that use an interactive mouse set the terminal mode to
different values. Though they're not entirely the same terminal mode
across programs, an emulator like vte (the library gnome-terminal
implements), changes the mouse cursor if the mouse mode is one of the
following:
- 1000: Mouse Click Tracking
- 1001: Mouse Highlight Tracking
- 1002: Mouse Cell Motion Tracking
- 1003: Mouse All Motion Tracking
- 1004: Mouse Focus Tracking
See 6acfa59dfc/src/vteseq.cc (L708)
for more information.
This commit adds functionality that changes the winit/glutin
`MouseCursor` when a mouse-listening mode of 1000-1004 is set. It
behaves similarly to when the window title changes.
This commit is contained in:
parent
ed91eb365e
commit
caddac918e
5 changed files with 71 additions and 11 deletions
17
src/ansi.rs
17
src/ansi.rs
|
@ -21,7 +21,7 @@ use vte;
|
|||
|
||||
use index::{Column, Line, Contains};
|
||||
|
||||
use ::Rgb;
|
||||
use ::{MouseCursor, Rgb};
|
||||
|
||||
// Parse color arguments
|
||||
//
|
||||
|
@ -178,6 +178,9 @@ pub trait Handler {
|
|||
/// OSC to set window title
|
||||
fn set_title(&mut self, &str) {}
|
||||
|
||||
/// Set the window's mouse cursor
|
||||
fn set_mouse_cursor(&mut self, MouseCursor) {}
|
||||
|
||||
/// Set the cursor style
|
||||
fn set_cursor_style(&mut self, _: Option<CursorStyle>) {}
|
||||
|
||||
|
@ -402,7 +405,9 @@ pub enum Mode {
|
|||
/// ?1000
|
||||
ReportMouseClicks = 1000,
|
||||
/// ?1002
|
||||
ReportMouseMotion = 1002,
|
||||
ReportCellMouseMotion = 1002,
|
||||
/// ?1003
|
||||
ReportAllMouseMotion = 1003,
|
||||
/// ?1004
|
||||
ReportFocusInOut = 1004,
|
||||
/// ?1006
|
||||
|
@ -427,12 +432,16 @@ impl Mode {
|
|||
12 => Mode::BlinkingCursor,
|
||||
25 => Mode::ShowCursor,
|
||||
1000 => Mode::ReportMouseClicks,
|
||||
1002 => Mode::ReportMouseMotion,
|
||||
1002 => Mode::ReportCellMouseMotion,
|
||||
1003 => Mode::ReportAllMouseMotion,
|
||||
1004 => Mode::ReportFocusInOut,
|
||||
1006 => Mode::SgrMouse,
|
||||
1049 => Mode::SwapScreenAndSetRestoreCursor,
|
||||
2004 => Mode::BracketedPaste,
|
||||
_ => return None
|
||||
_ => {
|
||||
trace!("[unhandled] mode={:?}", num);
|
||||
return None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Some(match num {
|
||||
|
|
|
@ -327,6 +327,10 @@ impl Display {
|
|||
self.window.set_title(&title);
|
||||
}
|
||||
|
||||
if let Some(mouse_cursor) = terminal.get_next_mouse_cursor() {
|
||||
self.window.set_mouse_cursor(mouse_cursor);
|
||||
}
|
||||
|
||||
if let Some(is_urgent) = terminal.next_is_urgent.take() {
|
||||
// We don't need to set the urgent flag if we already have the
|
||||
// user's attention.
|
||||
|
|
|
@ -81,6 +81,13 @@ use std::ops::Mul;
|
|||
pub use grid::Grid;
|
||||
pub use term::Term;
|
||||
|
||||
/// Facade around [winit's MouseCursor](glutin::MouseCursor)
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
pub enum MouseCursor {
|
||||
Arrow,
|
||||
Text,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Rgb {
|
||||
pub r: u8,
|
||||
|
|
|
@ -28,7 +28,7 @@ use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed};
|
|||
use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive};
|
||||
use selection::{self, Span, Selection};
|
||||
use config::{Config, VisualBellAnimation};
|
||||
use Rgb;
|
||||
use {MouseCursor, Rgb};
|
||||
|
||||
pub mod cell;
|
||||
pub mod color;
|
||||
|
@ -648,6 +648,9 @@ pub struct Term {
|
|||
/// Would be nice to avoid the allocation...
|
||||
next_title: Option<String>,
|
||||
|
||||
/// Got a request to set the mouse cursor; it's buffered here until the next draw
|
||||
next_mouse_cursor: Option<MouseCursor>,
|
||||
|
||||
/// Alternate grid
|
||||
alt_grid: Grid<Cell>,
|
||||
|
||||
|
@ -769,6 +772,11 @@ impl Term {
|
|||
self.next_title.take()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_next_mouse_cursor(&mut self) -> Option<MouseCursor> {
|
||||
self.next_mouse_cursor.take()
|
||||
}
|
||||
|
||||
pub fn new(config: &Config, size: SizeInfo) -> Term {
|
||||
let template = Cell::default();
|
||||
|
||||
|
@ -786,6 +794,7 @@ impl Term {
|
|||
|
||||
Term {
|
||||
next_title: None,
|
||||
next_mouse_cursor: None,
|
||||
dirty: false,
|
||||
visual_bell: VisualBell::new(config),
|
||||
next_is_urgent: None,
|
||||
|
@ -1168,6 +1177,12 @@ impl ansi::Handler for Term {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set the mouse cursor
|
||||
#[inline]
|
||||
fn set_mouse_cursor(&mut self, cursor: MouseCursor) {
|
||||
self.next_mouse_cursor = Some(cursor);
|
||||
}
|
||||
|
||||
/// A character to be displayed
|
||||
#[inline]
|
||||
fn input(&mut self, c: char) {
|
||||
|
@ -1767,8 +1782,15 @@ impl ansi::Handler for Term {
|
|||
},
|
||||
ansi::Mode::ShowCursor => self.mode.insert(mode::TermMode::SHOW_CURSOR),
|
||||
ansi::Mode::CursorKeys => self.mode.insert(mode::TermMode::APP_CURSOR),
|
||||
ansi::Mode::ReportMouseClicks => self.mode.insert(mode::TermMode::MOUSE_REPORT_CLICK),
|
||||
ansi::Mode::ReportMouseMotion => self.mode.insert(mode::TermMode::MOUSE_MOTION),
|
||||
ansi::Mode::ReportMouseClicks => {
|
||||
self.mode.insert(mode::TermMode::MOUSE_REPORT_CLICK);
|
||||
self.set_mouse_cursor(MouseCursor::Arrow);
|
||||
},
|
||||
ansi::Mode::ReportCellMouseMotion |
|
||||
ansi::Mode::ReportAllMouseMotion => {
|
||||
self.mode.insert(mode::TermMode::MOUSE_MOTION);
|
||||
self.set_mouse_cursor(MouseCursor::Arrow);
|
||||
},
|
||||
ansi::Mode::ReportFocusInOut => self.mode.insert(mode::TermMode::FOCUS_IN_OUT),
|
||||
ansi::Mode::BracketedPaste => self.mode.insert(mode::TermMode::BRACKETED_PASTE),
|
||||
ansi::Mode::SgrMouse => self.mode.insert(mode::TermMode::SGR_MOUSE),
|
||||
|
@ -1797,8 +1819,15 @@ impl ansi::Handler for Term {
|
|||
},
|
||||
ansi::Mode::ShowCursor => self.mode.remove(mode::TermMode::SHOW_CURSOR),
|
||||
ansi::Mode::CursorKeys => self.mode.remove(mode::TermMode::APP_CURSOR),
|
||||
ansi::Mode::ReportMouseClicks => self.mode.remove(mode::TermMode::MOUSE_REPORT_CLICK),
|
||||
ansi::Mode::ReportMouseMotion => self.mode.remove(mode::TermMode::MOUSE_MOTION),
|
||||
ansi::Mode::ReportMouseClicks => {
|
||||
self.mode.remove(mode::TermMode::MOUSE_REPORT_CLICK);
|
||||
self.set_mouse_cursor(MouseCursor::Text);
|
||||
},
|
||||
ansi::Mode::ReportCellMouseMotion |
|
||||
ansi::Mode::ReportAllMouseMotion => {
|
||||
self.mode.remove(mode::TermMode::MOUSE_MOTION);
|
||||
self.set_mouse_cursor(MouseCursor::Text);
|
||||
},
|
||||
ansi::Mode::ReportFocusInOut => self.mode.remove(mode::TermMode::FOCUS_IN_OUT),
|
||||
ansi::Mode::BracketedPaste => self.mode.remove(mode::TermMode::BRACKETED_PASTE),
|
||||
ansi::Mode::SgrMouse => self.mode.remove(mode::TermMode::SGR_MOUSE),
|
||||
|
|
|
@ -16,9 +16,12 @@ use std::fmt::{self, Display};
|
|||
use std::ops::Deref;
|
||||
|
||||
use gl;
|
||||
use glutin::{self, EventsLoop, WindowBuilder, Event, MouseCursor, CursorState, ControlFlow, ContextBuilder};
|
||||
use glutin::{self, ContextBuilder, ControlFlow, CursorState, Event, EventsLoop,
|
||||
MouseCursor as GlutinMouseCursor, WindowBuilder};
|
||||
use glutin::GlContext;
|
||||
|
||||
use MouseCursor;
|
||||
|
||||
use config::WindowConfig;
|
||||
|
||||
/// Window errors
|
||||
|
@ -200,7 +203,7 @@ impl Window {
|
|||
let window = ::glutin::GlWindow::new(window, context, &event_loop)?;
|
||||
|
||||
// Text cursor
|
||||
window.set_cursor(MouseCursor::Text);
|
||||
window.set_cursor(GlutinMouseCursor::Text);
|
||||
|
||||
// Set OpenGL symbol loader
|
||||
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
|
||||
|
@ -284,6 +287,14 @@ impl Window {
|
|||
self.window.set_title(title);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_mouse_cursor(&self, cursor: MouseCursor) {
|
||||
self.window.set_cursor(match cursor {
|
||||
MouseCursor::Arrow => GlutinMouseCursor::Arrow,
|
||||
MouseCursor::Text => GlutinMouseCursor::Text,
|
||||
});
|
||||
}
|
||||
|
||||
/// Set cursor visible
|
||||
pub fn set_cursor_visible(&mut self, visible: bool) {
|
||||
if visible != self.cursor_visible {
|
||||
|
|
Loading…
Reference in a new issue