1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 13:16:39 +03:00

macos (mostly): try harder to get initial dpi

There are a number of open issues that relate to getting the dpi
wrong when spawning a window. In theory it shouldn't matter because
we will immediately realize the difference and synthesize the correct
information, but evidence shows this isn't quite true.

What this commit does is:

* Override Connection::default_dpi() on macOS to return the
  effective_dpi from the active screen instead of the default
  non-retina dpi
* Adjust the Config::initial_size() method to accept an optional
  cell pixel dimension
* Add a helper function to wezterm-gui to compute the cell pixel
  dimensions given the config and the (usually default) dpi, and
  feed that through to Config::initial_size
* in the macos window impl, scale the computed geometry based on
  the ratio of the Connection::default_dpi and the default non-retina
  dpi.

This helps to avoid needing to do a fixup in the
https://github.com/wez/wezterm/issues/4966 case, and may help with
the various other macos quirky issues.

refs: https://github.com/wez/wezterm/issues/2958
refs: https://github.com/wez/wezterm/issues/3575
refs: https://github.com/wez/wezterm/issues/3900
refs: https://github.com/wez/wezterm/issues/4250
refs: https://github.com/wez/wezterm/issues/4285
refs: https://github.com/wez/wezterm/issues/4447
refs: https://github.com/wez/wezterm/issues/4851
refs: https://github.com/wez/wezterm/issues/4966
This commit is contained in:
Wez Furlong 2024-02-06 22:57:05 -07:00
parent 36ff6d5f44
commit 4f123a461b
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
11 changed files with 83 additions and 26 deletions

View File

@ -1444,21 +1444,24 @@ impl Config {
}
}
pub fn initial_size(&self, dpi: u32) -> TerminalSize {
pub fn initial_size(&self, dpi: u32, cell_pixel_dims: Option<(usize, usize)>) -> TerminalSize {
// If we aren't passed the actual values, guess at a plausible
// default set of pixel dimensions.
// This is based on "typical" 10 point font at "normal"
// pixel density.
// This will get filled in by the gui layer, but there is
// an edge case where we emit an iTerm image escape in
// the software update banner through the mux layer before
// the GUI has had a chance to update the pixel dimensions
// when running under X11.
// This is a bit gross.
let (cell_pixel_width, cell_pixel_height) = cell_pixel_dims.unwrap_or((8, 16));
TerminalSize {
rows: self.initial_rows as usize,
cols: self.initial_cols as usize,
// Guess at a plausible default set of pixel dimensions.
// This is based on "typical" 10 point font at "normal"
// pixel density.
// This will get filled in by the gui layer, but there is
// an edge case where we emit an iTerm image escape in
// the software update banner through the mux layer before
// the GUI has had a chance to update the pixel dimensions
// when running under X11.
// This is a bit gross.
pixel_width: 8 * self.initial_cols as usize,
pixel_height: 16 * self.initial_rows as usize,
pixel_width: cell_pixel_width * self.initial_cols as usize,
pixel_height: cell_pixel_height * self.initial_rows as usize,
dpi,
}
}

View File

@ -238,7 +238,7 @@ impl SpawnWindow {
cols,
..Default::default()
},
_ => config::configuration().initial_size(0),
_ => config::configuration().initial_size(0, None),
};
let (cmd_builder, cwd) = self.cmd_builder.to_command_builder();
@ -284,7 +284,7 @@ impl SpawnTab {
size = window
.get_by_idx(0)
.map(|tab| tab.get_size())
.unwrap_or_else(|| config::configuration().initial_size(0));
.unwrap_or_else(|| config::configuration().initial_size(0, None));
pane = window
.get_active()

View File

@ -279,8 +279,9 @@ impl GuiFrontEnd {
fn spawn_command(spawn: &SpawnCommand, spawn_where: SpawnWhere) {
let config = config::configuration();
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi()) as u32;
let size = config.initial_size(dpi);
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi());
let size =
config.initial_size(dpi as u32, crate::cell_pixel_dims(&config, dpi).ok());
let term_config = Arc::new(config::TermConfig::with_config(config));
crate::spawn::spawn_command_impl(spawn, spawn_where, size, None, term_config)

View File

@ -3,6 +3,7 @@
use crate::customglyph::BlockKey;
use crate::glyphcache::GlyphCache;
use crate::utilsprites::RenderMetrics;
use ::window::*;
use anyhow::{anyhow, Context};
use clap::builder::ValueParser;
@ -28,6 +29,7 @@ use unicode_normalization::UnicodeNormalization;
use wezterm_bidi::Direction;
use wezterm_client::domain::ClientDomain;
use wezterm_font::shaper::PresentationWidth;
use wezterm_font::FontConfiguration;
use wezterm_gui_subcommands::*;
use wezterm_mux_server_impl::update_mux_domains;
use wezterm_toast_notification::*;
@ -328,9 +330,14 @@ async fn spawn_tab_in_domain_if_mux_is_empty(
true
});
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi()) as u32;
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi());
let _tab = domain
.spawn(config.initial_size(dpi), cmd, None, window_id)
.spawn(
config.initial_size(dpi as u32, Some(cell_pixel_dims(&config, dpi)?)),
cmd,
None,
window_id,
)
.await?;
trigger_and_log_gui_attached(MuxDomain(domain.domain_id())).await;
Ok(())
@ -389,6 +396,15 @@ async fn trigger_and_log_gui_attached(domain: MuxDomain) {
}
}
fn cell_pixel_dims(config: &ConfigHandle, dpi: f64) -> anyhow::Result<(usize, usize)> {
let fontconfig = Rc::new(FontConfiguration::new(Some(config.clone()), dpi as usize)?);
let render_metrics = RenderMetrics::new(&fontconfig)?;
Ok((
render_metrics.cell_size.width as usize,
render_metrics.cell_size.height as usize,
))
}
async fn async_run_terminal_gui(
cmd: Option<CommandBuilder>,
opts: StartCommand,
@ -456,9 +472,14 @@ async fn async_run_terminal_gui(
domain.attach(Some(window_id)).await?;
let config = config::configuration();
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi()) as u32;
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi());
let tab = domain
.spawn(config.initial_size(dpi), cmd.clone(), None, window_id)
.spawn(
config.initial_size(dpi as u32, Some(cell_pixel_dims(&config, dpi)?)),
cmd.clone(),
None,
window_id,
)
.await?;
let mut window = mux
.get_window_mut(window_id)
@ -585,7 +606,7 @@ impl Publish {
window_id,
command,
command_dir: None,
size: config.initial_size(0),
size: config.initial_size(0, None),
workspace: workspace.unwrap_or(
config
.default_workspace

View File

@ -2949,7 +2949,15 @@ impl TermWindow {
if !have_panes_in_domain {
let config = config::configuration();
let _tab = domain
.spawn(config.initial_size(dpi), None, None, window)
.spawn(
config.initial_size(
dpi,
Some(crate::cell_pixel_dims(&config, dpi as f64)?),
),
None,
None,
window,
)
.await?;
}

View File

@ -533,7 +533,13 @@ impl super::TermWindow {
}
pub fn reset_font_and_window_size(&mut self, window: &Window) -> anyhow::Result<()> {
let size = self.config.initial_size(self.dimensions.dpi as u32);
let size = self.config.initial_size(
self.dimensions.dpi as u32,
Some(crate::cell_pixel_dims(
&self.config,
self.dimensions.dpi as f64,
)?),
);
self.set_window_size(size, window)
}

View File

@ -6,7 +6,10 @@ use std::sync::Arc;
impl super::TermWindow {
pub fn spawn_command(&self, spawn: &SpawnCommand, spawn_where: SpawnWhere) {
let size = if spawn_where == SpawnWhere::NewWindow {
self.config.initial_size(self.dimensions.dpi as u32)
self.config.initial_size(
self.dimensions.dpi as u32,
crate::cell_pixel_dims(&self.config, self.dimensions.dpi as f64).ok(),
)
} else {
self.terminal_size
};

View File

@ -291,7 +291,7 @@ async fn async_run(cmd: Option<CommandBuilder>) -> anyhow::Result<()> {
let _tab = mux
.default_domain()
.spawn(config.initial_size(0), cmd, None, *window_id)
.spawn(config.initial_size(0, None), cmd, None, *window_id)
.await?;
}
Ok(())

View File

@ -94,7 +94,7 @@ impl SpawnCommand {
)
.to_string();
let size = config.initial_size(0);
let size = config.initial_size(0, None);
let spawned = client
.spawn_v2(codec::SpawnV2 {

View File

@ -110,6 +110,14 @@ impl ConnectionOps for Connection {
}
}
fn default_dpi(&self) -> f64 {
if let Ok(screens) = self.screens() {
screens.active.effective_dpi.unwrap_or(crate::DEFAULT_DPI)
} else {
crate::DEFAULT_DPI
}
}
fn terminate_message_loop(&self) {
unsafe {
// bounce via an event callback to encourage stop to apply

View File

@ -452,6 +452,13 @@ impl Window {
x,
y,
} = conn.resolve_geometry(geometry);
let scale_factor = (conn.default_dpi() / crate::DEFAULT_DPI) as usize;
let width = width / scale_factor;
let height = height / scale_factor;
let x = x.map(|x| x / scale_factor as i32);
let y = y.map(|y| y / scale_factor as i32);
let initial_pos = match (x, y) {
(Some(x), Some(y)) => Some(ScreenPoint::new(x as isize, y as isize)),
_ => None,