From ec1ae68cfc9a14391afa2380a7f3a4f8f32dc813 Mon Sep 17 00:00:00 2001 From: Murarth Date: Fri, 3 Jan 2020 23:14:11 -0700 Subject: [PATCH] X11: Properly update window size constraints on DPI change (#1356) * In `WindowBuilderExtUnix` methods, use `Size` instead of `LogicalSize` --- src/platform/unix.rs | 10 ++--- src/platform_impl/linux/mod.rs | 4 +- .../linux/x11/event_processor.rs | 2 + src/platform_impl/linux/x11/window.rs | 43 ++++++++++++------- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index fbf8a920..0484d71e 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -5,7 +5,7 @@ use std::{os::raw, ptr, sync::Arc}; use smithay_client_toolkit::window::{ButtonState, Theme}; use crate::{ - dpi::LogicalSize, + dpi::Size, event_loop::{EventLoop, EventLoopWindowTarget}, monitor::MonitorHandle, window::{Window, WindowBuilder}, @@ -380,9 +380,9 @@ pub trait WindowBuilderExtUnix { /// Build window with `_GTK_THEME_VARIANT` hint set to the specified value. Currently only relevant on X11. fn with_gtk_theme_variant(self, variant: String) -> Self; /// Build window with resize increment hint. Only implemented on X11. - fn with_resize_increments(self, increments: LogicalSize) -> Self; + fn with_resize_increments>(self, increments: S) -> Self; /// Build window with base size hint. Only implemented on X11. - fn with_base_size(self, base_size: LogicalSize) -> Self; + fn with_base_size>(self, base_size: S) -> Self; /// Build window with a given application ID. It should match the `.desktop` file distributed with /// your program. Only relevant on Wayland. @@ -431,13 +431,13 @@ impl WindowBuilderExtUnix for WindowBuilder { } #[inline] - fn with_resize_increments(mut self, increments: LogicalSize) -> Self { + fn with_resize_increments>(mut self, increments: S) -> Self { self.platform_specific.resize_increments = Some(increments.into()); self } #[inline] - fn with_base_size(mut self, base_size: LogicalSize) -> Self { + fn with_base_size>(mut self, base_size: S) -> Self { self.platform_specific.base_size = Some(base_size.into()); self } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index e3bfe78f..dfb18341 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -34,8 +34,8 @@ const BACKEND_PREFERENCE_ENV_VAR: &str = "WINIT_UNIX_BACKEND"; pub struct PlatformSpecificWindowBuilderAttributes { pub visual_infos: Option, pub screen_id: Option, - pub resize_increments: Option<(u32, u32)>, - pub base_size: Option<(u32, u32)>, + pub resize_increments: Option, + pub base_size: Option, pub class: Option<(String, String)>, pub override_redirect: bool, pub x11_window_types: Vec, diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 0becc2e8..014b9b02 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -420,6 +420,7 @@ impl EventProcessor { new_scale_factor, width, height, + &shared_state_lock, ); let old_inner_size = PhysicalSize::new(width, height); @@ -1134,6 +1135,7 @@ impl EventProcessor { new_monitor.scale_factor, width, height, + &*window.shared_state.lock(), ); let window_id = crate::window::WindowId( diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index dcbfd59c..d8bb99e8 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -47,6 +47,8 @@ pub struct SharedState { pub frame_extents: Option, pub min_inner_size: Option, pub max_inner_size: Option, + pub resize_increments: Option, + pub base_size: Option, pub visibility: Visibility, } @@ -83,6 +85,8 @@ impl SharedState { frame_extents: None, min_inner_size: None, max_inner_size: None, + resize_increments: None, + base_size: None, }) } } @@ -235,7 +239,7 @@ impl UnownedWindow { ) }; - let window = UnownedWindow { + let mut window = UnownedWindow { xconn: Arc::clone(xconn), xwindow, root, @@ -324,6 +328,7 @@ impl UnownedWindow { let mut max_inner_size = window_attrs .max_inner_size .map(|size| size.to_physical::(dpi_factor)); + if !window_attrs.resizable { if util::wm_name_is_one_of(&["Xfwm4"]) { warn!("To avoid a WM bug, disabling resizing has no effect on Xfwm4"); @@ -331,9 +336,11 @@ impl UnownedWindow { max_inner_size = Some(dimensions.into()); min_inner_size = Some(dimensions.into()); - let mut shared_state_lock = window.shared_state.lock(); - shared_state_lock.min_inner_size = window_attrs.min_inner_size; - shared_state_lock.max_inner_size = window_attrs.max_inner_size; + let mut shared_state = window.shared_state.get_mut(); + shared_state.min_inner_size = window_attrs.min_inner_size; + shared_state.max_inner_size = window_attrs.max_inner_size; + shared_state.resize_increments = pl_attribs.resize_increments; + shared_state.base_size = pl_attribs.base_size; } } @@ -341,8 +348,16 @@ impl UnownedWindow { normal_hints.set_size(Some(dimensions)); normal_hints.set_min_size(min_inner_size.map(Into::into)); normal_hints.set_max_size(max_inner_size.map(Into::into)); - normal_hints.set_resize_increments(pl_attribs.resize_increments); - normal_hints.set_base_size(pl_attribs.base_size); + normal_hints.set_resize_increments( + pl_attribs + .resize_increments + .map(|size| size.to_physical::(dpi_factor).into()), + ); + normal_hints.set_base_size( + pl_attribs + .base_size + .map(|size| size.to_physical::(dpi_factor).into()), + ); xconn.set_normal_hints(window.xwindow, normal_hints).queue(); } @@ -1086,18 +1101,16 @@ impl UnownedWindow { new_dpi_factor: f64, width: u32, height: u32, + shared_state: &SharedState, ) -> (u32, u32) { let scale_factor = new_dpi_factor / old_dpi_factor; self.update_normal_hints(|normal_hints| { - let dpi_adjuster = |(width, height): (u32, u32)| -> (u32, u32) { - let new_width = width as f64 * scale_factor; - let new_height = height as f64 * scale_factor; - (new_width.round() as u32, new_height.round() as u32) - }; - let max_size = normal_hints.get_max_size().map(&dpi_adjuster); - let min_size = normal_hints.get_min_size().map(&dpi_adjuster); - let resize_increments = normal_hints.get_resize_increments().map(&dpi_adjuster); - let base_size = normal_hints.get_base_size().map(&dpi_adjuster); + let dpi_adjuster = + |size: Size| -> (u32, u32) { size.to_physical::(new_dpi_factor).into() }; + let max_size = shared_state.max_inner_size.map(&dpi_adjuster); + let min_size = shared_state.min_inner_size.map(&dpi_adjuster); + let resize_increments = shared_state.resize_increments.map(&dpi_adjuster); + let base_size = shared_state.base_size.map(&dpi_adjuster); normal_hints.set_max_size(max_size); normal_hints.set_min_size(min_size); normal_hints.set_resize_increments(resize_increments);