diff --git a/docs/changelog.md b/docs/changelog.md index b7333b1bf..4152aebf0 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -59,6 +59,8 @@ As features stabilize some brief notes about them will accumulate here. * Windows: closing a window while the debug overlay was active could leave a lingering wezterm-gui.exe running. #3522 * Windows: inconsistencies with win32 input mode. Thanks to @kreudom! #2235 +* macOS: font size is zoomed or window appears empty when first launched on a + secondary monitor with different scaling settings from the primary monitor. #3503 ### 20230408-112425-69ae8472 diff --git a/wezterm-gui/src/termwindow/resize.rs b/wezterm-gui/src/termwindow/resize.rs index fb8d9ce64..872e70030 100644 --- a/wezterm-gui/src/termwindow/resize.rs +++ b/wezterm-gui/src/termwindow/resize.rs @@ -350,6 +350,20 @@ impl super::TermWindow { self.dimensions.pixel_height as f32, ))); + if simple_dpi_change && cfg!(target_os = "macos") { + // Spooky action at a distance: on macOS, NSWindow::isZoomed can falsely + // return YES in situations such as the current screen changing. + // That causes window_state to believe that we are MAXIMIZED. + // We cannot easily detect that in the window layer, but at this + // layer, if we realize that the dpi was the only thing that changed + // then remove the MAXIMIZED state so that the can_resize check + // in adjust_font_scale will not block us from adapting to the new + // DPI. This is gross and it would be better handled at the macOS + // layer. + // + self.window_state -= WindowState::MAXIMIZED; + } + let dpi_changed = dimensions.dpi != self.dimensions.dpi; let font_scale_changed = font_scale != self.fonts.get_font_scale(); let scale_changed = dpi_changed || font_scale_changed; diff --git a/window/src/os/macos/window.rs b/window/src/os/macos/window.rs index 127fed723..57d7b7b04 100644 --- a/window/src/os/macos/window.rs +++ b/window/src/os/macos/window.rs @@ -744,10 +744,10 @@ impl WindowOps for Window { } fn set_inner_size(&self, width: usize, height: usize) { - Connection::with_window_inner( - self.id, - move |inner| Ok(inner.set_inner_size(width, height)), - ); + Connection::with_window_inner(self.id, move |inner| { + inner.set_inner_size(width, height); + Ok(()) + }); } fn set_window_position(&self, coords: ScreenPoint) { @@ -1149,7 +1149,7 @@ impl WindowInner { } } - fn set_inner_size(&mut self, width: usize, height: usize) -> Dimensions { + fn set_inner_size(&mut self, width: usize, height: usize) { unsafe { let frame = NSView::frame(*self.view as *mut _); let backing_frame = NSView::convertRectToBacking(*self.view as *mut _, frame); @@ -1160,15 +1160,9 @@ impl WindowInner { NSSize::new(width as f64 / scale, height as f64 / scale), ); - let frame = NSView::frame(*self.view as *mut _); - let backing_frame = NSView::convertRectToBacking(*self.view as *mut _, frame); - let width = backing_frame.size.width; - let height = backing_frame.size.height; - Dimensions { - pixel_width: width as usize, - pixel_height: height as usize, - dpi: (crate::DEFAULT_DPI * (backing_frame.size.width / frame.size.width)) as usize, - } + // setContentSize_ doesn't explicitly invalidate, + // so we need to do it ourselves + self.invalidate(); } } @@ -2738,6 +2732,11 @@ impl WindowView { let live_resizing = inner.live_resizing; + // Note: isZoomed can falsely return YES in situations such as + // the current screen changing. We cannot detect that case here. + // There is some logic to compensate for this in + // wezterm-gui/src/termwindow/resize.rs. + // let is_zoomed = !is_full_screen && inner.window.as_ref().map_or(false, |window| { let window = window.load();