diff --git a/src/ansi.rs b/src/ansi.rs index ec139294..3d66b497 100644 --- a/src/ansi.rs +++ b/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) {} @@ -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 { diff --git a/src/display.rs b/src/display.rs index 8e3d8814..89403194 100644 --- a/src/display.rs +++ b/src/display.rs @@ -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. diff --git a/src/lib.rs b/src/lib.rs index a8539328..1f3fcc96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, diff --git a/src/term/mod.rs b/src/term/mod.rs index 98e08e6c..712247c4 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -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, + /// Got a request to set the mouse cursor; it's buffered here until the next draw + next_mouse_cursor: Option, + /// Alternate grid alt_grid: Grid, @@ -769,6 +772,11 @@ impl Term { self.next_title.take() } + #[inline] + pub fn get_next_mouse_cursor(&mut self) -> Option { + 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), diff --git a/src/window.rs b/src/window.rs index e42151fd..aec4b76d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -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 {