diff --git a/term/src/terminalstate/performer.rs b/term/src/terminalstate/performer.rs index a01fb4c28..3520a632a 100644 --- a/term/src/terminalstate/performer.rs +++ b/term/src/terminalstate/performer.rs @@ -5,6 +5,7 @@ use crate::terminalstate::{ use crate::{ClipboardSelection, Position, TerminalState, VisibleRowIndex, DCS, ST}; use log::{debug, error}; use num_traits::FromPrimitive; +use ordered_float::NotNan; use std::fmt::Write; use std::ops::{Deref, DerefMut}; use termwiz::cell::{grapheme_column_width, Cell, CellAttributes, SemanticType}; @@ -630,6 +631,37 @@ impl<'a> Performer<'a> { } } OperatingSystemCommand::ITermProprietary(iterm) => match iterm { + ITermProprietary::RequestCellSize => { + let screen = self.screen(); + let height = screen.physical_rows; + let width = screen.physical_cols; + + let scale = if screen.dpi == 0 { + 1.0 + } else { + // Since iTerm2 is a macOS specific piece + // of software, it uses the macOS default dpi + // if 72 for the basis of its scale, regardless + // of the host base dpi. + screen.dpi as f32 / 72. + }; + let width = (self.pixel_width as f32 / width as f32) / scale; + let height = (self.pixel_height as f32 / height as f32) / scale; + + let response = OperatingSystemCommand::ITermProprietary( + ITermProprietary::ReportCellSize { + width_pixels: NotNan::new(width).unwrap(), + height_pixels: NotNan::new(height).unwrap(), + scale: if screen.dpi == 0 { + None + } else { + Some(NotNan::new(scale).unwrap()) + }, + }, + ); + write!(self.writer, "{}", response).ok(); + self.writer.flush().ok(); + } ITermProprietary::File(image) => self.set_image(*image), ITermProprietary::SetUserVar { name, value } => { self.user_vars.insert(name.clone(), value.clone()); diff --git a/termwiz/src/escape/osc.rs b/termwiz/src/escape/osc.rs index 9cac57e5e..6a90dd5b7 100644 --- a/termwiz/src/escape/osc.rs +++ b/termwiz/src/escape/osc.rs @@ -812,10 +812,14 @@ pub enum ITermProprietary { /// Request that the terminal send a ReportCellSize response RequestCellSize, /// The response to RequestCellSize. The height and width are the dimensions - /// of a cell measured in points + /// of a cell measured in points according to the docs, but in practice, they + /// are actually pixels. + /// If scale is_some(), the width and height will be multiplied by scale to + /// get the true device dimensions ReportCellSize { - height_points: NotNan, - width_points: NotNan, + height_pixels: NotNan, + width_pixels: NotNan, + scale: Option>, }, /// Place a string in the systems pasteboard Copy(String), @@ -1145,8 +1149,18 @@ impl ITermProprietary { if osc.len() == 3 && keyword == "ReportCellSize" && p1.is_some() { if let Some(p1) = p1 { return Ok(ITermProprietary::ReportCellSize { - height_points: NotNan::new(p1.parse()?)?, - width_points: NotNan::new(String::from_utf8_lossy(osc[2]).parse()?)?, + height_pixels: NotNan::new(p1.parse()?)?, + width_pixels: NotNan::new(String::from_utf8_lossy(osc[2]).parse()?)?, + scale: None, + }); + } + } + if osc.len() == 4 && keyword == "ReportCellSize" && p1.is_some() { + if let Some(p1) = p1 { + return Ok(ITermProprietary::ReportCellSize { + height_pixels: NotNan::new(p1.parse()?)?, + width_pixels: NotNan::new(String::from_utf8_lossy(osc[2]).parse()?)?, + scale: Some(NotNan::new(String::from_utf8_lossy(osc[3]).parse()?)?), }); } } @@ -1216,9 +1230,18 @@ impl Display for ITermProprietary { } RequestCellSize => write!(f, "ReportCellSize")?, ReportCellSize { - height_points, - width_points, - } => write!(f, "ReportCellSize={};{}", height_points, width_points)?, + height_pixels, + width_pixels, + scale: None, + } => write!(f, "ReportCellSize={height_pixels:.1};{width_pixels:.1}")?, + ReportCellSize { + height_pixels, + width_pixels, + scale: Some(scale), + } => write!( + f, + "ReportCellSize={height_pixels:.1};{width_pixels:.1};{scale:.1}", + )?, Copy(s) => write!(f, "Copy=;{}", base64::encode(s))?, ReportVariable(s) => write!(f, "ReportVariable={}", base64::encode(s))?, SetUserVar { name, value } => { @@ -1615,11 +1638,24 @@ mod test { assert_eq!( parse( &["1337", "ReportCellSize=12.0", "15.5"], - "\x1b]1337;ReportCellSize=12;15.5\x1b\\" + "\x1b]1337;ReportCellSize=12.0;15.5\x1b\\" ), OperatingSystemCommand::ITermProprietary(ITermProprietary::ReportCellSize { - height_points: NotNan::new(12.0).unwrap(), - width_points: NotNan::new(15.5).unwrap() + height_pixels: NotNan::new(12.0).unwrap(), + width_pixels: NotNan::new(15.5).unwrap(), + scale: None, + }) + ); + + assert_eq!( + parse( + &["1337", "ReportCellSize=12.0", "15.5", "2.0"], + "\x1b]1337;ReportCellSize=12.0;15.5;2.0\x1b\\" + ), + OperatingSystemCommand::ITermProprietary(ITermProprietary::ReportCellSize { + height_pixels: NotNan::new(12.0).unwrap(), + width_pixels: NotNan::new(15.5).unwrap(), + scale: Some(NotNan::new(2.0).unwrap()), }) );