From fd349f182267f8060cd7a59c9f73bb7c5b055049 Mon Sep 17 00:00:00 2001 From: David Craven Date: Mon, 10 Dec 2018 20:55:40 +0100 Subject: [PATCH] Use smithay-client-toolkit's dpi handling. (#724) * Use smithay-client-toolkit's dpi handling. * Add CHANGELOG entry. --- CHANGELOG.md | 1 + Cargo.toml | 2 +- src/platform/linux/wayland/event_loop.rs | 6 +- src/platform/linux/wayland/window.rs | 121 +++-------------------- 4 files changed, 16 insertions(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b2f2e78..311911e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Derive `Ord` and `PartialOrd` for `VirtualKeyCode` enum. - On Windows, fix issue where hovering or dropping a non file item would create a panic. - On Wayland, fix resizing and DPI calculation when a `wl_output` is removed without sending a `leave` event to the `wl_surface`, such as disconnecting a monitor from a laptop. +- On Wayland, DPI calculation is handled by smithay-client-toolkit. - On X11, `WindowBuilder::with_min_dimensions` and `WindowBuilder::with_max_dimensions` now correctly account for DPI. # Version 0.18.0 (2018-11-07) diff --git a/Cargo.toml b/Cargo.toml index 3b0dcc13..915c3b07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ features = [ [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] wayland-client = { version = "0.21", features = [ "dlopen", "egl", "cursor"] } -smithay-client-toolkit = "0.4" +smithay-client-toolkit = "0.4.3" x11-dl = "2.18.3" parking_lot = "0.6" percent-encoding = "1.0" diff --git a/src/platform/linux/wayland/event_loop.rs b/src/platform/linux/wayland/event_loop.rs index 3f9ac7d2..ee483487 100644 --- a/src/platform/linux/wayland/event_loop.rs +++ b/src/platform/linux/wayland/event_loop.rs @@ -123,12 +123,10 @@ impl EventsLoop { }, }; - let cb_store = store.clone(); - let env = Environment::from_display_with_cb( &display, &mut event_queue, - move |event, registry| { + move |event, registry| { match event { GlobalEvent::New { id, ref interface, version } => { if interface == "wl_seat" { @@ -138,8 +136,6 @@ impl EventsLoop { GlobalEvent::Removed { id, ref interface } => { if interface == "wl_seat" { seat_manager.remove_seat(id) - } else if interface == "wl_output" { - cb_store.lock().unwrap().remove_output(id); } }, } diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index 01c6de12..62a74bef 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -6,10 +6,10 @@ use dpi::{LogicalPosition, LogicalSize}; use platform::{MonitorId as PlatformMonitorId, PlatformSpecificWindowBuilderAttributes as PlAttributes}; use window::MonitorId as RootMonitorId; +use sctk::surface::{get_dpi_factor, get_outputs}; use sctk::window::{ConceptFrame, Event as WEvent, Window as SWindow}; use sctk::reexports::client::{Display, Proxy}; -use sctk::reexports::client::protocol::{wl_seat, wl_surface, wl_output}; -use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests; +use sctk::reexports::client::protocol::{wl_seat, wl_surface}; use sctk::reexports::client::protocol::wl_surface::RequestsTrait as SurfaceRequests; use sctk::output::OutputMgr; @@ -19,7 +19,6 @@ use platform::platform::wayland::event_loop::{get_available_monitors, get_primar pub struct Window { surface: Proxy, frame: Arc>>, - monitors: Arc>, // Monitors this window is currently on outputs: OutputMgr, // Access to info for all monitors size: Arc>, kill_switch: (Arc>, Arc>), @@ -33,39 +32,11 @@ impl Window { // Create the window let size = Arc::new(Mutex::new((width, height))); - // monitor tracking - let monitor_list = Arc::new(Mutex::new(MonitorList::new())); - - let surface = evlp.env.compositor.create_surface(|surface| { - let list = monitor_list.clone(); - let omgr = evlp.env.outputs.clone(); - let window_store = evlp.store.clone(); - surface.implement(move |event, surface| match event { - wl_surface::Event::Enter { output } => { - let dpi_change = list.lock().unwrap().add_output(MonitorId { - proxy: output, - mgr: omgr.clone(), - }); - if let Some(dpi) = dpi_change { - if surface.version() >= 3 { - // without version 3 we can't be dpi aware - window_store.lock().unwrap().dpi_change(&surface, dpi); - surface.set_buffer_scale(dpi); - } - } - }, - wl_surface::Event::Leave { output } => { - let dpi_change = list.lock().unwrap().del_output(&output); - if let Some(dpi) = dpi_change { - if surface.version() >= 3 { - // without version 3 we can't be dpi aware - window_store.lock().unwrap().dpi_change(&surface, dpi); - surface.set_buffer_scale(dpi); - } - } - } - }, ()) - }).unwrap(); + let window_store = evlp.store.clone(); + let surface = evlp.env.create_surface(move |dpi, surface| { + window_store.lock().unwrap().dpi_change(&surface, dpi); + surface.set_buffer_scale(dpi); + }); let window_store = evlp.store.clone(); let my_surface = surface.clone(); @@ -148,7 +119,6 @@ impl Window { frame: Arc::downgrade(&frame), current_dpi: 1, new_dpi: None, - monitors: monitor_list.clone(), }); evlp.evq.borrow_mut().sync_roundtrip().unwrap(); @@ -156,7 +126,6 @@ impl Window { display: evlp.display.clone(), surface: surface, frame: frame, - monitors: monitor_list, outputs: evlp.env.outputs.clone(), size: size, kill_switch: (kill_switch, evlp.cleanup_needed.clone()), @@ -236,7 +205,7 @@ impl Window { #[inline] pub fn hidpi_factor(&self) -> i32 { - self.monitors.lock().unwrap().compute_hidpi_factor() + get_dpi_factor(&self.surface) } pub fn set_decorations(&self, decorate: bool) { @@ -295,10 +264,11 @@ impl Window { } pub fn get_current_monitor(&self) -> MonitorId { - // we don't know how much each monitor sees us so... - // just return the most recent one ? - let guard = self.monitors.lock().unwrap(); - guard.monitors.last().unwrap().clone() + let output = get_outputs(&self.surface).last().unwrap().clone(); + MonitorId { + proxy: output, + mgr: self.outputs.clone(), + } } pub fn get_available_monitors(&self) -> VecDeque { @@ -332,7 +302,6 @@ struct InternalWindow { frame: Weak>>, current_dpi: i32, new_dpi: Option, - monitors: Arc> } pub struct WindowStore { @@ -378,18 +347,6 @@ impl WindowStore { } } - pub fn remove_output(&mut self, output: u32) { - for window in &mut self.windows { - let dpi = window.monitors.lock().unwrap().output_disappeared(output); - if window.surface.version() >= 3 { - // without version 3 we can't be dpi aware - window.new_dpi = Some(dpi); - window.surface.set_buffer_scale(dpi); - window.need_refresh = true; - } - } - } - fn dpi_change(&mut self, surface: &Proxy, new: i32) { for window in &mut self.windows { if surface.equals(&window.surface) { @@ -424,55 +381,3 @@ impl WindowStore { } } } - -/* - * Monitor list with some covenience method to compute DPI - */ - -struct MonitorList { - monitors: Vec -} - -impl MonitorList { - fn new() -> MonitorList { - MonitorList { - monitors: Vec::new() - } - } - - fn compute_hidpi_factor(&self) -> i32 { - let mut factor = 1; - for monitor_id in &self.monitors { - let monitor_dpi = monitor_id.get_hidpi_factor(); - if monitor_dpi > factor { factor = monitor_dpi; } - } - factor - } - - fn add_output(&mut self, monitor: MonitorId) -> Option { - let old_dpi = self.compute_hidpi_factor(); - let monitor_dpi = monitor.get_hidpi_factor(); - self.monitors.push(monitor); - if monitor_dpi > old_dpi { - Some(monitor_dpi) - } else { - None - } - } - - fn del_output(&mut self, output: &Proxy) -> Option { - let old_dpi = self.compute_hidpi_factor(); - self.monitors.retain(|m| !m.proxy.equals(output)); - let new_dpi = self.compute_hidpi_factor(); - if new_dpi != old_dpi { - Some(new_dpi) - } else { - None - } - } - - fn output_disappeared(&mut self, id: u32) -> i32 { - self.monitors.retain(|m| m.get_native_identifier() != id); - self.compute_hidpi_factor() - } -}