Skip to content

Commit

Permalink
Add support for OSC 22 escape sequence
Browse files Browse the repository at this point in the history
Add support for OSC 22 escape sequence to allow changing mouse cursor
shapes. While the escape sequence could help some users with the mouse
UX in TUI applications using mouse mode, it could obscure common mouse
mode indication which is the `Text` cursor. Thus OSC 22 is disabled by
default and could be enabled with `terminal.osc22` configuration option.

Fixes alacritty#7119.
  • Loading branch information
kchibisov committed Sep 28, 2023
1 parent 47d5007 commit 92fa601
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Bindings to create and navigate tabs on macOS
- Support startup notify protocol to raise initial window on Wayland/X11
- Debug option `prefer_egl` to prioritize EGL over other display APIs
- Escape sequence to change mouse cursor shape (OSC 22);
use `terminal.osc22` to enable it

### Changed

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 14 additions & 4 deletions alacritty/src/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,9 @@ pub struct Display {
/// The state of the timer for frame scheduling.
pub frame_timer: FrameTimer,

/// Mouse icon set by the user with the OSC 22 escape sequence.
pub osc22_cursor: Option<CursorIcon>,

// Mouse point position when highlighting hints.
hint_mouse_point: Option<Point>,

Expand Down Expand Up @@ -516,6 +519,7 @@ impl Display {
colors: List::from(&config.colors),
pending_update: Default::default(),
pending_renderer_update: Default::default(),
osc22_cursor: None,
debug_damage,
damage_rects,
raw_window_handle,
Expand Down Expand Up @@ -1048,11 +1052,17 @@ impl Display {
self.window.set_mouse_cursor(CursorIcon::Pointer);
} else if self.highlighted_hint.is_some() {
self.hint_mouse_point = None;
if term.mode().intersects(TermMode::MOUSE_MODE) && !term.mode().contains(TermMode::VI) {
self.window.set_mouse_cursor(CursorIcon::Default);
let cursor = if let Some(cursor) = self.osc22_cursor {
cursor
} else if term.mode().intersects(TermMode::MOUSE_MODE)
&& !term.mode().contains(TermMode::VI)
{
CursorIcon::Default
} else {
self.window.set_mouse_cursor(CursorIcon::Text);
}
CursorIcon::Text
};

self.window.set_mouse_cursor(cursor);
}

dirty |= self.highlighted_hint != highlighted_hint;
Expand Down
4 changes: 4 additions & 0 deletions alacritty/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,10 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
let text = format(self.ctx.size_info().into());
self.ctx.write_to_pty(text.into_bytes());
},
TerminalEvent::MouseCursorIcon(icon) => {
self.ctx.display().osc22_cursor = icon;
self.reset_mouse_cursor();
},
TerminalEvent::PtyWrite(text) => self.ctx.write_to_pty(text.into_bytes()),
TerminalEvent::MouseCursorDirty => self.reset_mouse_cursor(),
TerminalEvent::CursorBlinkingChange => self.ctx.update_cursor_blinking(),
Expand Down
2 changes: 2 additions & 0 deletions alacritty/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,8 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
mouse_state
} else if self.ctx.display().highlighted_hint.as_ref().map_or(false, hint_highlighted) {
CursorIcon::Pointer
} else if let Some(cursor) = self.ctx.display().osc22_cursor {
cursor
} else if !self.ctx.modifiers().state().shift_key() && self.ctx.mouse_mode() {
CursorIcon::Default
} else {
Expand Down
1 change: 1 addition & 0 deletions alacritty_terminal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ version = "0.1.2-dev"
[dependencies]
base64 = "0.13.0"
bitflags = { version = "2.2.1", features = ["serde"] }
cursor-icon = "1.0.0"
home = "0.5.5"
libc = "0.2"
log = "0.4"
Expand Down
5 changes: 4 additions & 1 deletion alacritty_terminal/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ pub struct Config {

#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq, Default)]
pub struct Terminal {
// OSC 52 handling (clipboard handling).
/// OSC 52 handling (clipboard handling).
pub osc52: Osc52,

/// Allow to set cursor shape with the OSC 22 escape.
pub osc22: bool,
}

#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq, Default)]
Expand Down
8 changes: 8 additions & 0 deletions alacritty_terminal/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::borrow::Cow;
use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;

use cursor_icon::CursorIcon;

use crate::term::color::Rgb;
use crate::term::ClipboardType;

Expand All @@ -17,6 +19,11 @@ pub enum Event {
/// Window title change.
Title(String),

/// Mouse cursor icon change.
///
/// `None` indicates that it was unset.
MouseCursorIcon(Option<CursorIcon>),

/// Reset to the default window title.
ResetTitle,

Expand Down Expand Up @@ -65,6 +72,7 @@ impl Debug for Event {
Event::Title(title) => write!(f, "Title({title})"),
Event::CursorBlinkingChange => write!(f, "CursorBlinkingChange"),
Event::MouseCursorDirty => write!(f, "MouseCursorDirty"),
Event::MouseCursorIcon(icon) => write!(f, "MouseCursorIcon({icon:?})"),
Event::ResetTitle => write!(f, "ResetTitle"),
Event::Wakeup => write!(f, "Wakeup"),
Event::Bell => write!(f, "Bell"),
Expand Down
14 changes: 14 additions & 0 deletions alacritty_terminal/src/term/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::sync::Arc;
use std::{cmp, mem, ptr, slice, str};

use bitflags::bitflags;
use cursor_icon::CursorIcon;
use log::{debug, trace};
use unicode_width::UnicodeWidthChar;
use vte::ansi::{Hyperlink as VteHyperlink, Rgb as VteRgb};
Expand Down Expand Up @@ -467,6 +468,10 @@ impl<T> Term<T> {

self.config = config.terminal.clone();

if !self.config.osc22 {
self.event_proxy.send_event(Event::MouseCursorIcon(None));
}

// Damage everything on config updates.
self.mark_fully_damaged();
}
Expand Down Expand Up @@ -1694,6 +1699,7 @@ impl<T: EventListener> Handler for Term<T> {
self.mode.insert(TermMode::default());

self.event_proxy.send_event(Event::CursorBlinkingChange);
self.event_proxy.send_event(Event::MouseCursorIcon(None));
self.mark_fully_damaged();
}

Expand Down Expand Up @@ -1926,6 +1932,14 @@ impl<T: EventListener> Handler for Term<T> {
self.event_proxy.send_event(Event::CursorBlinkingChange);
}

#[inline]
fn set_mouse_cursor_icon(&mut self, icon: CursorIcon) {
if self.config.osc22 {
trace!("Requesting to set mouse cursor icon to {:?}", icon);
self.event_proxy.send_event(Event::MouseCursorIcon(Some(icon)));
}
}

#[inline]
fn set_cursor_shape(&mut self, shape: CursorShape) {
trace!("Setting cursor shape {:?}", shape);
Expand Down
1 change: 1 addition & 0 deletions docs/escape_support.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ brevity.
| `OSC 10` | IMPLEMENTED | |
| `OSC 11` | IMPLEMENTED | |
| `OSC 12` | IMPLEMENTED | |
| `OSC 22` | IMPLEMENTED | |
| `OSC 50` | IMPLEMENTED | Only `CursorShape` is supported |
| `OSC 52` | IMPLEMENTED | Only Clipboard and primary selection supported |
| `OSC 104` | IMPLEMENTED | |
Expand Down
7 changes: 7 additions & 0 deletions extra/man/alacritty.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,13 @@ This section documents the *[terminal]* table of the configuration file.

Default: _"OnlyCopy"_

*osc22* <boolean>

Controls the ability to change the mouse cursor shape with the escape
sequences trying to improve application mouse mode user experience.

Default: _false_

# Mouse

This section documents the *[mouse]* table of the configuration file.
Expand Down

0 comments on commit 92fa601

Please sign in to comment.