Skip to content

Commit

Permalink
wayland: respond to config.dpi changes faster
Browse files Browse the repository at this point in the history
This is a baby step towards handling dpi_by_screen.
I don't want to do the actualy per-screen stuff here;
it touches stuff around the edges of SCTK and there is a pending,
significant, rewrite of that code needed to upgrade to a more
recent version of SCTK + wayland-protocols, and I don't want to waste
my effort on the intermediate state.
#3996 (comment)

refs: #4096
  • Loading branch information
wez committed Aug 6, 2023
1 parent ede7e84 commit ef94fc8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 37 deletions.
24 changes: 14 additions & 10 deletions window/src/os/wayland/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,24 @@ const BORDER_SIZE: u32 = 12;
const HEADER_SIZE: u32 = 30;

/// Configuration for ConceptFrame
#[derive(Clone, Default)]
#[derive(Clone)]
pub struct ConceptConfig {
pub font_config: Option<Rc<FontConfiguration>>,
pub config: Option<ConfigHandle>,
pub default_frame: WindowFrameConfig,
pub config: ConfigHandle,
}

impl Default for ConceptConfig {
fn default() -> Self {
Self {
font_config: None,
config: config::configuration(),
}
}
}

impl ConceptConfig {
pub fn colors(&self) -> &WindowFrameConfig {
self.config
.as_ref()
.map(|c| &c.window_frame)
.unwrap_or(&self.default_frame)
&self.config.window_frame
}
}

Expand Down Expand Up @@ -514,9 +519,8 @@ impl ConceptFrame {
} else {
self.config
.config
.as_ref()
.map(|cfg| cfg.window_decorations.contains(WindowDecorations::TITLE))
.unwrap_or(true)
.window_decorations
.contains(WindowDecorations::TITLE)
}
}
}
Expand Down
78 changes: 51 additions & 27 deletions window/src/os/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pub struct WaylandWindowInner {
window_id: usize,
pub(crate) events: WindowEventSender,
surface: Attached<WlSurface>,
surface_factor: i32,
surface_factor: f64,
copy_and_paste: Arc<Mutex<CopyAndPaste>>,
window: Option<toolkit::window::Window<ConceptFrame>>,
dimensions: Dimensions,
Expand All @@ -150,7 +150,7 @@ pub struct WaylandWindowInner {
font_config: Rc<FontConfiguration>,
text_cursor: Option<Rect>,
appearance: Appearance,
config: Option<ConfigHandle>,
config: ConfigHandle,
// cache the title for comparison to avoid spamming
// the compositor with updates that don't actually change it
title: Option<String>,
Expand Down Expand Up @@ -247,6 +247,10 @@ impl WaylandWindow {
where
F: 'static + FnMut(WindowEvent, &Window),
{
let config = match config {
Some(c) => c.clone(),
None => config::configuration(),
};
let conn = WaylandConnection::get()
.ok_or_else(|| {
anyhow!(
Expand Down Expand Up @@ -289,7 +293,7 @@ impl WaylandWindow {
let dimensions = Dimensions {
pixel_width: width,
pixel_height: height,
dpi: crate::DEFAULT_DPI as usize,
dpi: config.dpi.unwrap_or(crate::DEFAULT_DPI) as usize,
};

let theme_manager = None;
Expand Down Expand Up @@ -320,10 +324,7 @@ impl WaylandWindow {
window.set_app_id(class_name.to_string());
window.set_resizable(true);
window.set_title(name.to_string());
let decorations = config
.as_ref()
.map(|c| c.window_decorations)
.unwrap_or(WindowDecorations::default());
let decorations = config.window_decorations;

window.set_decorate(if decorations == WindowDecorations::NONE {
Decorations::None
Expand All @@ -338,8 +339,7 @@ impl WaylandWindow {

window.set_frame_config(ConceptConfig {
font_config: Some(Rc::clone(&font_config)),
config: config.cloned(),
..Default::default()
config: config.clone(),
});

window.set_min_size(Some((32, 32)));
Expand All @@ -352,12 +352,12 @@ impl WaylandWindow {
let inner = Rc::new(RefCell::new(WaylandWindowInner {
window_id,
font_config,
config: config.cloned(),
config,
key_repeat: None,
copy_and_paste,
events: WindowEventSender::new(event_handler),
surface,
surface_factor: 1,
surface_factor: 1.0,
invalidated: false,
window: Some(window),
dimensions,
Expand Down Expand Up @@ -607,19 +607,19 @@ impl WaylandWindowInner {
}
}

fn get_dpi_factor(&self) -> i32 {
self.dimensions.dpi as i32 / crate::DEFAULT_DPI as i32
fn get_dpi_factor(&self) -> f64 {
self.dimensions.dpi as f64 / crate::DEFAULT_DPI as f64
}

fn surface_to_pixels(&self, surface: i32) -> i32 {
surface * self.get_dpi_factor()
(surface as f64 * self.get_dpi_factor()).ceil() as i32
}

fn pixels_to_surface(&self, pixels: i32) -> i32 {
// Take care to round up, otherwise we can lose a pixel
// and that can effectively lose the final row of the
// terminal
((pixels as f64) / (self.get_dpi_factor() as f64)).ceil() as i32
((pixels as f64) / self.get_dpi_factor()).ceil() as i32
}

fn dispatch_pending_event(&mut self) {
Expand Down Expand Up @@ -655,10 +655,14 @@ impl WaylandWindowInner {

if let Some((mut w, mut h)) = pending.configure.take() {
if self.window.is_some() {
let factor = get_surface_scale_factor(&self.surface);
let factor = get_surface_scale_factor(&self.surface) as f64;
let old_dimensions = self.dimensions;

// FIXME: teach this how to resolve dpi_by_screen
let dpi = self.config.dpi.unwrap_or(factor * crate::DEFAULT_DPI) as usize;

// Do this early because this affects surface_to_pixels/pixels_to_surface below!
self.dimensions.dpi = factor as usize * crate::DEFAULT_DPI as usize;
self.dimensions.dpi = dpi;

let mut pixel_width = self.surface_to_pixels(w.try_into().unwrap());
let mut pixel_height = self.surface_to_pixels(h.try_into().unwrap());
Expand All @@ -681,12 +685,12 @@ impl WaylandWindowInner {
let new_dimensions = Dimensions {
pixel_width: pixel_width.try_into().unwrap(),
pixel_height: pixel_height.try_into().unwrap(),
dpi: factor as usize * crate::DEFAULT_DPI as usize,
dpi,
};

// Only trigger a resize if the new dimensions are different;
// this makes things more efficient and a little more smooth
if new_dimensions != self.dimensions {
if new_dimensions != old_dimensions {
self.dimensions = new_dimensions;

self.events.dispatch(WindowEvent::Resized {
Expand Down Expand Up @@ -718,13 +722,13 @@ impl WaylandWindowInner {
// simply detaching the buffer can cause wlroots-derived
// compositors consider the window to be unconfigured.
if let Ok((_bytes, buffer)) = pool.buffer(
factor,
factor,
factor * 4,
factor as i32,
factor as i32,
(factor * 4.0) as i32,
wayland_client::protocol::wl_shm::Format::Argb8888,
) {
self.surface.attach(Some(&buffer), 0, 0);
self.surface.set_buffer_scale(factor);
self.surface.set_buffer_scale(factor as i32);
self.surface_factor = factor;
}
}
Expand Down Expand Up @@ -1170,7 +1174,10 @@ impl WaylandWindowInner {
Dimensions {
pixel_width: pixel_width as _,
pixel_height: pixel_height as _,
dpi: factor as usize * crate::DEFAULT_DPI as usize,
dpi: self
.config
.dpi
.unwrap_or(factor as f64 * crate::DEFAULT_DPI) as usize,
}
}

Expand Down Expand Up @@ -1227,13 +1234,30 @@ impl WaylandWindowInner {
}

fn config_did_change(&mut self, config: &ConfigHandle) {
self.config.replace(config.clone());
let dpi_changed =
self.config.dpi != config.dpi || self.config.dpi_by_screen != config.dpi_by_screen;
self.config = config.clone();
if let Some(window) = self.window.as_mut() {
window.set_frame_config(ConceptConfig {
font_config: Some(Rc::clone(&self.font_config)),
config: Some(config.clone()),
..Default::default()
config: config.clone(),
});

if dpi_changed {
// Synthesize a Resized event; we'll figure out the actual
// dpi to use there.
{
let mut pending = self.pending_event.lock().unwrap();
if pending.configure.is_none() {
pending.configure.replace((
self.dimensions.pixel_width as u32,
self.dimensions.pixel_height as u32,
));
}
}
self.dispatch_pending_event();
}

// I tried re-applying the config to window.set_decorate
// here, but it crashed weston. I figure that users
// would prefer to manually close wezterm to change
Expand Down

0 comments on commit ef94fc8

Please sign in to comment.