From a9621170f782f29fea4da505c685220fcd4d0103 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sat, 28 Sep 2019 09:01:14 -0700 Subject: [PATCH] window: on macos, query the dpi and improve resize/scaling handling --- src/frontend/software/termwindow.rs | 43 +++++++++++++++++++++++++++++ window/src/os/macos/window.rs | 31 +++++++++++++++++---- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/frontend/software/termwindow.rs b/src/frontend/software/termwindow.rs index 1a677d2cb..1ee0d2448 100644 --- a/src/frontend/software/termwindow.rs +++ b/src/frontend/software/termwindow.rs @@ -44,6 +44,7 @@ pub struct TermWindow { fonts: Rc, _config: Arc, cell_size: Size, + dimensions: Dimensions, mux_window_id: MuxWindowId, descender: f64, descender_row: isize, @@ -186,6 +187,40 @@ impl WindowCallbacks for TermWindow { fn resize(&mut self, dimensions: Dimensions) { let mux = Mux::get().unwrap(); if let Some(window) = mux.get_window(self.mux_window_id) { + if dimensions.dpi != self.dimensions.dpi { + self.fonts.change_scaling(1., dimensions.dpi as f64 / 96.); + let metrics = self + .fonts + .default_font_metrics() + .expect("failed to get font metrics!?"); + + let (cell_height, cell_width) = ( + metrics.cell_height.ceil() as usize, + metrics.cell_width.ceil() as usize, + ); + + let surface = Rc::new(ImageTexture::new(4096, 4096)); + let atlas = + RefCell::new(Atlas::new(&surface).expect("failed to create new texture atlas")); + + let descender_row = (cell_height as f64 + metrics.descender) as isize; + let descender_plus_one = (1 + descender_row).min(cell_height as isize - 1); + let descender_plus_two = (2 + descender_row).min(cell_height as isize - 1); + let strike_row = descender_row / 2; + + self.descender = metrics.descender; + self.descender_row = descender_row; + self.descender_plus_one = descender_plus_one; + self.descender_plus_two = descender_plus_two; + self.strike_row = strike_row; + self.glyph_cache.borrow_mut().clear(); + self.atlas = atlas; + + self.cell_size = Size::new(cell_width as isize, cell_height as isize); + } + + self.dimensions = dimensions; + let size = portable_pty::PtySize { rows: dimensions.pixel_height as u16 / self.cell_size.height as u16, cols: dimensions.pixel_width as u16 / self.cell_size.width as u16, @@ -306,6 +341,14 @@ impl TermWindow { descender_plus_one, descender_plus_two, strike_row, + dimensions: Dimensions { + pixel_width: width, + pixel_height: height, + // This is the default dpi; we'll get a resize + // event to inform us of the true dpi if it is + // different from this value + dpi: 96, + }, glyph_cache: RefCell::new(HashMap::new()), atlas, clipboard: Arc::new(SystemClipboard::new()), diff --git a/window/src/os/macos/window.rs b/window/src/os/macos/window.rs index 56055f6ff..df7d0d1f9 100644 --- a/window/src/os/macos/window.rs +++ b/window/src/os/macos/window.rs @@ -84,6 +84,11 @@ impl Window { window.setContentView_(*view); window.setDelegate_(*view); + let frame = NSView::frame(*view); + let backing_frame = NSView::convertRectToBacking(*view, frame); + let width = backing_frame.size.width; + let height = backing_frame.size.height; + let window_inner = Rc::new(RefCell::new(WindowInner { window_id, window, @@ -96,6 +101,14 @@ impl Window { let window = Window(window_id); inner.borrow_mut().callbacks.created(&window); + // Synthesize a resize event immediately; this allows + // the embedding application an opportunity to discover + // the dpi and adjust for display scaling + inner.borrow_mut().callbacks.resize(Dimensions { + pixel_width: width as usize, + pixel_height: height as usize, + dpi: (96.0 * (backing_frame.size.width / frame.size.width)) as usize, + }); Ok(window) } @@ -196,6 +209,7 @@ pub fn superclass(this: &Object) -> &'static Class { struct MacGraphicsContext<'a> { buffer: &'a mut dyn BitmapImage, + dpi: usize, } impl<'a> PaintContext for MacGraphicsContext<'a> { @@ -212,7 +226,7 @@ impl<'a> PaintContext for MacGraphicsContext<'a> { Dimensions { pixel_width, pixel_height, - dpi: 96, + dpi: self.dpi, } } @@ -445,21 +459,25 @@ impl WindowView { extern "C" fn did_resize(this: &mut Object, _sel: Sel, _notification: id) { let frame = unsafe { NSView::frame(this as *mut _) }; - let width = frame.size.width; - let height = frame.size.height; + let backing_frame = unsafe { NSView::convertRectToBacking(this as *mut _, frame) }; + let width = backing_frame.size.width; + let height = backing_frame.size.height; if let Some(this) = Self::get_this(this) { this.inner.borrow_mut().callbacks.resize(Dimensions { pixel_width: width as usize, pixel_height: height as usize, - dpi: 96, + dpi: (96.0 * (backing_frame.size.width / frame.size.width)) as usize, }); } } extern "C" fn draw_rect(this: &mut Object, _sel: Sel, _dirty_rect: NSRect) { let frame = unsafe { NSView::frame(this as *mut _) }; - let width = frame.size.width; - let height = frame.size.height; + let backing_frame = unsafe { NSView::convertRectToBacking(this as *mut _, frame) }; + + let width = backing_frame.size.width; + let height = backing_frame.size.height; + if let Some(this) = Self::get_this(this) { let mut inner = this.inner.borrow_mut(); let mut buffer = this.buffer.borrow_mut(); @@ -471,6 +489,7 @@ impl WindowView { let mut ctx = MacGraphicsContext { buffer: &mut *buffer, + dpi: (96.0 * backing_frame.size.width / frame.size.width) as usize, }; inner.callbacks.paint(&mut ctx);