mirror of
https://github.com/wez/wezterm.git
synced 2024-12-22 21:01:36 +03:00
term: support utf8 mouse reporting (DECSET 1005)
This commit is contained in:
parent
cb31c35b99
commit
ed63d728bf
@ -41,6 +41,8 @@ As features stabilize some brief notes about them will accumulate here.
|
|||||||
event.
|
event.
|
||||||
* [pane:inject_output](config/lua/pane/inject_output.md) method
|
* [pane:inject_output](config/lua/pane/inject_output.md) method
|
||||||
* [ResetTerminal](config/lua/keyassignment/ResetTerminal.md) key assignment
|
* [ResetTerminal](config/lua/keyassignment/ResetTerminal.md) key assignment
|
||||||
|
* Support for Utf8 mouse reporting (DECSET 1005).
|
||||||
|
[#2613](https://github.com/wez/wezterm/issues/2613)
|
||||||
|
|
||||||
#### Fixed
|
#### Fixed
|
||||||
* Wayland: key repeat gets stuck after pressing two keys in quick succession.
|
* Wayland: key repeat gets stuck after pressing two keys in quick succession.
|
||||||
|
@ -55,6 +55,7 @@ pub(crate) enum CharSet {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub(crate) enum MouseEncoding {
|
pub(crate) enum MouseEncoding {
|
||||||
X10,
|
X10,
|
||||||
|
Utf8,
|
||||||
SGR,
|
SGR,
|
||||||
SgrPixels,
|
SgrPixels,
|
||||||
}
|
}
|
||||||
@ -1760,6 +1761,25 @@ impl TerminalState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mode::SetDecPrivateMode(DecPrivateMode::Code(DecPrivateModeCode::Utf8Mouse)) => {
|
||||||
|
self.mouse_encoding = MouseEncoding::Utf8;
|
||||||
|
self.last_mouse_move.take();
|
||||||
|
}
|
||||||
|
Mode::ResetDecPrivateMode(DecPrivateMode::Code(DecPrivateModeCode::Utf8Mouse)) => {
|
||||||
|
self.mouse_encoding = MouseEncoding::X10;
|
||||||
|
self.last_mouse_move.take();
|
||||||
|
}
|
||||||
|
Mode::QueryDecPrivateMode(DecPrivateMode::Code(DecPrivateModeCode::Utf8Mouse)) => {
|
||||||
|
self.decqrm_response(
|
||||||
|
mode,
|
||||||
|
true,
|
||||||
|
match self.mouse_encoding {
|
||||||
|
MouseEncoding::Utf8 => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Mode::SetDecPrivateMode(DecPrivateMode::Code(
|
Mode::SetDecPrivateMode(DecPrivateMode::Code(
|
||||||
DecPrivateModeCode::SixelScrollsRight,
|
DecPrivateModeCode::SixelScrollsRight,
|
||||||
)) => {
|
)) => {
|
||||||
@ -1821,9 +1841,6 @@ impl TerminalState {
|
|||||||
DecPrivateModeCode::XTermAltSendsEscape,
|
DecPrivateModeCode::XTermAltSendsEscape,
|
||||||
)) => {}
|
)) => {}
|
||||||
|
|
||||||
Mode::SetDecPrivateMode(DecPrivateMode::Code(DecPrivateModeCode::Utf8Mouse))
|
|
||||||
| Mode::ResetDecPrivateMode(DecPrivateMode::Code(DecPrivateModeCode::Utf8Mouse)) => {}
|
|
||||||
|
|
||||||
Mode::SetDecPrivateMode(DecPrivateMode::Unspecified(_))
|
Mode::SetDecPrivateMode(DecPrivateMode::Unspecified(_))
|
||||||
| Mode::ResetDecPrivateMode(DecPrivateMode::Unspecified(_))
|
| Mode::ResetDecPrivateMode(DecPrivateMode::Unspecified(_))
|
||||||
| Mode::SaveDecPrivateMode(DecPrivateMode::Unspecified(_))
|
| Mode::SaveDecPrivateMode(DecPrivateMode::Unspecified(_))
|
||||||
|
@ -4,15 +4,38 @@ use crate::TerminalState;
|
|||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
|
||||||
impl TerminalState {
|
impl TerminalState {
|
||||||
/// Encode a coordinate value using X10 encoding.
|
/// Encode a coordinate value using X10 encoding or Utf8 encoding.
|
||||||
/// X10 has a theoretical maximum coordinate value of 255-33, but
|
/// Out of bounds coords are reported as the 0 byte value.
|
||||||
/// because we emit UTF-8 we are effectively capped at the maximum
|
fn encode_coord(&self, value: i64, dest: &mut Vec<u8>) {
|
||||||
/// single byte character value of 127, with coordinates capping
|
// Convert to 1-based and offset into the printable character range
|
||||||
/// out at 127-33.
|
let value = value + 1 + 32;
|
||||||
/// This isn't "fixable" in X10 encoding, applications should
|
if self.mouse_encoding == MouseEncoding::Utf8 {
|
||||||
/// use the superior SGR mouse encoding scheme instead.
|
if value < 0x800 {
|
||||||
fn legacy_mouse_coord(position: i64) -> char {
|
let mut utf8 = [0; 2];
|
||||||
position.max(0).saturating_add(1 + 32).min(127) as u8 as char
|
dest.extend_from_slice(
|
||||||
|
(char::from_u32(value as u32).unwrap())
|
||||||
|
.encode_utf8(&mut utf8)
|
||||||
|
.as_bytes(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// out of range
|
||||||
|
dest.push(0);
|
||||||
|
}
|
||||||
|
} else if value < 0x100 {
|
||||||
|
dest.push(value as u8);
|
||||||
|
} else {
|
||||||
|
// out of range
|
||||||
|
dest.push(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_x10_or_utf8(&mut self, event: MouseEvent, button: i8) -> anyhow::Result<()> {
|
||||||
|
let mut buf = vec![b'\x1b', b'[', b'M', (32 + button) as u8];
|
||||||
|
self.encode_coord(event.x as i64, &mut buf);
|
||||||
|
self.encode_coord(event.y, &mut buf);
|
||||||
|
self.writer.write(&buf)?;
|
||||||
|
self.writer.flush()?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_report_button_number(&self, event: &MouseEvent) -> (i8, MouseButton) {
|
fn mouse_report_button_number(&self, event: &MouseEvent) -> (i8, MouseButton) {
|
||||||
@ -76,14 +99,7 @@ impl TerminalState {
|
|||||||
)?;
|
)?;
|
||||||
self.writer.flush()?;
|
self.writer.flush()?;
|
||||||
} else if self.mouse_tracking || self.button_event_mouse || self.any_event_mouse {
|
} else if self.mouse_tracking || self.button_event_mouse || self.any_event_mouse {
|
||||||
write!(
|
self.encode_x10_or_utf8(event, button)?;
|
||||||
self.writer,
|
|
||||||
"\x1b[M{}{}{}",
|
|
||||||
(32 + button) as u8 as char,
|
|
||||||
Self::legacy_mouse_coord(event.x as i64),
|
|
||||||
Self::legacy_mouse_coord(event.y),
|
|
||||||
)?;
|
|
||||||
self.writer.flush()?;
|
|
||||||
} else if self.screen.is_alt_screen_active() {
|
} else if self.screen.is_alt_screen_active() {
|
||||||
// Send cursor keys instead (equivalent to xterm's alternateScroll mode)
|
// Send cursor keys instead (equivalent to xterm's alternateScroll mode)
|
||||||
for _ in 0..self.config.alternate_buffer_wheel_scroll_speed() {
|
for _ in 0..self.config.alternate_buffer_wheel_scroll_speed() {
|
||||||
@ -132,14 +148,7 @@ impl TerminalState {
|
|||||||
)?;
|
)?;
|
||||||
self.writer.flush()?;
|
self.writer.flush()?;
|
||||||
} else {
|
} else {
|
||||||
write!(
|
self.encode_x10_or_utf8(event, button)?;
|
||||||
self.writer,
|
|
||||||
"\x1b[M{}{}{}",
|
|
||||||
(32 + button) as u8 as char,
|
|
||||||
Self::legacy_mouse_coord(event.x as i64),
|
|
||||||
Self::legacy_mouse_coord(event.y),
|
|
||||||
)?;
|
|
||||||
self.writer.flush()?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -176,14 +185,7 @@ impl TerminalState {
|
|||||||
self.writer.flush()?;
|
self.writer.flush()?;
|
||||||
} else {
|
} else {
|
||||||
let release_button = 3;
|
let release_button = 3;
|
||||||
write!(
|
self.encode_x10_or_utf8(event, release_button)?;
|
||||||
self.writer,
|
|
||||||
"\x1b[M{}{}{}",
|
|
||||||
(32 + release_button) as u8 as char,
|
|
||||||
Self::legacy_mouse_coord(event.x as i64),
|
|
||||||
Self::legacy_mouse_coord(event.y),
|
|
||||||
)?;
|
|
||||||
self.writer.flush()?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,14 +244,7 @@ impl TerminalState {
|
|||||||
)?;
|
)?;
|
||||||
self.writer.flush()?;
|
self.writer.flush()?;
|
||||||
} else {
|
} else {
|
||||||
write!(
|
self.encode_x10_or_utf8(event, button)?;
|
||||||
self.writer,
|
|
||||||
"\x1b[M{}{}{}",
|
|
||||||
(32 + button) as u8 as char,
|
|
||||||
Self::legacy_mouse_coord(event.x as i64),
|
|
||||||
Self::legacy_mouse_coord(event.y),
|
|
||||||
)?;
|
|
||||||
self.writer.flush()?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user