1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

parse and respond to XTSMGRAPHICS queries

refs: https://github.com/wez/wezterm/issues/609
This commit is contained in:
Wez Furlong 2021-04-01 22:42:28 -07:00
parent c4cac94aab
commit 3dfdd08b79
2 changed files with 162 additions and 1 deletions

View File

@ -15,7 +15,8 @@ use std::sync::mpsc::{channel, Sender};
use std::sync::Arc;
use termwiz::escape::csi::{
Cursor, CursorStyle, DecPrivateMode, DecPrivateModeCode, Device, Edit, EraseInDisplay,
EraseInLine, Mode, Sgr, TabulationClear, TerminalMode, TerminalModeCode, Window,
EraseInLine, Mode, Sgr, TabulationClear, TerminalMode, TerminalModeCode, Window, XtSmGraphics,
XtSmGraphicsAction, XtSmGraphicsItem, XtSmGraphicsStatus,
};
use termwiz::escape::osc::{
ChangeColorPair, ColorOrQuery, FinalTermSemanticPrompt, ITermFileData, ITermProprietary,
@ -1778,6 +1779,48 @@ impl TerminalState {
self.writer.write(b"\x1b[0n").ok();
self.writer.flush().ok();
}
Device::XtSmGraphics(g) => {
let response = if matches!(g.item, XtSmGraphicsItem::Unspecified(_)) {
XtSmGraphics {
item: g.item,
action_or_status: XtSmGraphicsStatus::InvalidItem.to_i64(),
value: vec![],
}
} else {
match g.action() {
None | Some(XtSmGraphicsAction::SetToValue) => XtSmGraphics {
item: g.item,
action_or_status: XtSmGraphicsStatus::InvalidAction.to_i64(),
value: vec![],
},
Some(XtSmGraphicsAction::ResetToDefault) => XtSmGraphics {
item: g.item,
action_or_status: XtSmGraphicsStatus::Success.to_i64(),
value: vec![],
},
Some(XtSmGraphicsAction::ReadMaximumAllowedValue)
| Some(XtSmGraphicsAction::ReadAttribute) => match g.item {
XtSmGraphicsItem::Unspecified(_) => unreachable!("checked above"),
XtSmGraphicsItem::NumberOfColorRegisters => XtSmGraphics {
item: g.item,
action_or_status: XtSmGraphicsStatus::Success.to_i64(),
value: vec![65536],
},
XtSmGraphicsItem::RegisGraphicsGeometry
| XtSmGraphicsItem::SixelGraphicsGeometry => XtSmGraphics {
item: g.item,
action_or_status: XtSmGraphicsStatus::Success.to_i64(),
value: vec![self.pixel_width as i64, self.pixel_height as i64],
},
},
}
};
let dev = Device::XtSmGraphics(response);
write!(self.writer, "\x1b[{}", dev).ok();
self.writer.flush().ok();
}
}
}

View File

@ -169,6 +169,115 @@ pub enum DeviceAttributes {
Vt420(DeviceAttributeFlags),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum XtSmGraphicsItem {
NumberOfColorRegisters,
SixelGraphicsGeometry,
RegisGraphicsGeometry,
Unspecified(i64),
}
impl Display for XtSmGraphicsItem {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match self {
Self::NumberOfColorRegisters => write!(f, "1"),
Self::SixelGraphicsGeometry => write!(f, "2"),
Self::RegisGraphicsGeometry => write!(f, "3"),
Self::Unspecified(n) => write!(f, "{}", n),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum XtSmGraphicsAction {
ReadAttribute,
ResetToDefault,
SetToValue,
ReadMaximumAllowedValue,
}
impl XtSmGraphicsAction {
pub fn to_i64(&self) -> i64 {
match self {
Self::ReadAttribute => 1,
Self::ResetToDefault => 2,
Self::SetToValue => 3,
Self::ReadMaximumAllowedValue => 4,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum XtSmGraphicsStatus {
Success,
InvalidItem,
InvalidAction,
Failure,
}
impl XtSmGraphicsStatus {
pub fn to_i64(&self) -> i64 {
match self {
Self::Success => 0,
Self::InvalidItem => 1,
Self::InvalidAction => 2,
Self::Failure => 3,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct XtSmGraphics {
pub item: XtSmGraphicsItem,
pub action_or_status: i64,
pub value: Vec<i64>,
}
impl XtSmGraphics {
pub fn action(&self) -> Option<XtSmGraphicsAction> {
match self.action_or_status {
1 => Some(XtSmGraphicsAction::ReadAttribute),
2 => Some(XtSmGraphicsAction::ResetToDefault),
3 => Some(XtSmGraphicsAction::SetToValue),
4 => Some(XtSmGraphicsAction::ReadMaximumAllowedValue),
_ => None,
}
}
pub fn status(&self) -> Option<XtSmGraphicsStatus> {
match self.action_or_status {
0 => Some(XtSmGraphicsStatus::Success),
1 => Some(XtSmGraphicsStatus::InvalidItem),
2 => Some(XtSmGraphicsStatus::InvalidAction),
3 => Some(XtSmGraphicsStatus::Failure),
_ => None,
}
}
pub fn parse(params: &[CsiParam]) -> Result<CSI, ()> {
Ok(CSI::Device(Box::new(Device::XtSmGraphics(XtSmGraphics {
item: match params.get(0).ok_or(())? {
CsiParam::Integer(1) => XtSmGraphicsItem::NumberOfColorRegisters,
CsiParam::Integer(2) => XtSmGraphicsItem::SixelGraphicsGeometry,
CsiParam::Integer(3) => XtSmGraphicsItem::RegisGraphicsGeometry,
CsiParam::Integer(n) => XtSmGraphicsItem::Unspecified(*n),
_ => return Err(()),
},
action_or_status: match params.get(1).ok_or(())? {
CsiParam::Integer(n) => *n,
_ => return Err(()),
},
value: params[2..]
.iter()
.filter_map(|p| match p {
CsiParam::Integer(n) => Some(*n),
_ => None,
})
.collect(),
}))))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Device {
DeviceAttributes(DeviceAttributes),
@ -180,6 +289,7 @@ pub enum Device {
/// https://github.com/mintty/mintty/issues/881
/// https://gitlab.gnome.org/GNOME/vte/-/issues/235
RequestTerminalNameAndVersion,
XtSmGraphics(XtSmGraphics),
}
impl Display for Device {
@ -198,6 +308,13 @@ impl Display for Device {
Device::RequestSecondaryDeviceAttributes => write!(f, ">c")?,
Device::RequestTerminalNameAndVersion => write!(f, ">q")?,
Device::StatusReport => write!(f, "5n")?,
Device::XtSmGraphics(g) => {
write!(f, "?{};{}", g.item, g.action_or_status)?;
for v in &g.value {
write!(f, ";{}", v)?;
}
write!(f, "S")?;
}
};
Ok(())
}
@ -1369,6 +1486,7 @@ impl<'a> CSIParser<'a> {
('P', &[]) => parse!(Edit, DeleteCharacter, params),
('R', &[]) => parse!(Cursor, ActivePositionReport, line, col, params),
('S', &[]) => parse!(Edit, ScrollUp, params),
('S', &[b'?']) => XtSmGraphics::parse(params),
('T', &[]) => parse!(Edit, ScrollDown, params),
('W', &[]) => parse!(Cursor, TabulationControl, params),
('X', &[]) => parse!(Edit, EraseCharacter, params),