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:
parent
36ff6d5f44
commit
4f123a461b
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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?;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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(())
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user