From fdb5fc2d6635c1d37f851c1870703001da21807c Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 8 Jul 2022 09:54:42 -0700 Subject: [PATCH] wayland: implement wezterm.gui.screens() Hook it up for resolving geometry, but note that wayland doesn't allow positioning and we don't expose a way to set width/height based on screen right now. --- window/src/os/wayland/connection.rs | 61 ++++++++++++++++++++++++++++- window/src/os/wayland/window.rs | 26 +++++------- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/window/src/os/wayland/connection.rs b/window/src/os/wayland/connection.rs index 7b51823c0..7b92a19ef 100644 --- a/window/src/os/wayland/connection.rs +++ b/window/src/os/wayland/connection.rs @@ -3,8 +3,9 @@ use super::pointer::*; use super::window::*; use crate::connection::ConnectionOps; use crate::os::x11::keyboard::Keyboard; +use crate::screen::{ScreenInfo, Screens}; use crate::spawn::*; -use crate::Connection; +use crate::{Connection, ScreenRect}; use anyhow::{bail, Context}; use mio::unix::SourceFd; use mio::{Events, Interest, Poll, Token}; @@ -365,4 +366,62 @@ impl ConnectionOps for WaylandConnection { self.windows.borrow_mut().clear(); res } + + fn screens(&self) -> anyhow::Result { + let mut by_name = HashMap::new(); + let mut virtual_rect: ScreenRect = euclid::rect(0, 0, 0, 0); + for output in self.environment.borrow().get_all_outputs() { + toolkit::output::with_output_info(&output, |info| { + let name = if info.name.is_empty() { + format!("{} {}", info.model, info.make) + } else { + info.name.clone() + }; + + let (width, height) = info + .modes + .iter() + .find(|mode| mode.is_current) + .map(|mode| mode.dimensions) + .unwrap_or((info.physical_size.0, info.physical_size.1)); + + let rect = euclid::rect( + info.location.0 as isize, + info.location.1 as isize, + width as isize, + height as isize, + ); + + virtual_rect = virtual_rect.union(&rect); + by_name.insert(name.clone(), ScreenInfo { name, rect }); + }); + } + + // The main screen is the one either at the origin of + // the virtual area, or if that doesn't exist for some weird + // reason, the screen closest to the origin. + let main = by_name + .values() + .min_by_key(|screen| { + screen + .rect + .origin + .to_f32() + .distance_to(euclid::Point2D::origin()) + .abs() as isize + }) + .ok_or_else(|| anyhow::anyhow!("no screens were found"))? + .clone(); + + // We don't yet know how to determine the active screen, + // so assume the main screen. + let active = main.clone(); + + Ok(Screens { + main, + active, + by_name, + virtual_rect, + }) + } } diff --git a/window/src/os/wayland/window.rs b/window/src/os/wayland/window.rs index ce0413db4..6f7e3e8c8 100644 --- a/window/src/os/wayland/window.rs +++ b/window/src/os/wayland/window.rs @@ -5,13 +5,14 @@ use crate::connection::ConnectionOps; use crate::os::wayland::connection::WaylandConnection; use crate::os::x11::keyboard::Keyboard; use crate::{ - Clipboard, Connection, Dimensions, MouseCursor, Point, RequestedWindowGeometry, ScreenPoint, - Window, WindowEvent, WindowEventSender, WindowKeyEvent, WindowOps, WindowState, + Clipboard, Connection, Dimensions, MouseCursor, Point, RequestedWindowGeometry, + ResolvedGeometry, ScreenPoint, Window, WindowEvent, WindowEventSender, WindowKeyEvent, + WindowOps, WindowState, }; use anyhow::{anyhow, bail, Context}; use async_io::Timer; use async_trait::async_trait; -use config::{ConfigHandle, DimensionContext}; +use config::ConfigHandle; use filedescriptor::FileDescriptor; use promise::{Future, Promise}; use raw_window_handle::unix::WaylandHandle; @@ -275,19 +276,12 @@ impl WaylandWindow { .borrow_mut() .insert(surface.as_ref().id(), window_id); - // TODO: populate these dimension contexts based on the wayland OutputInfo - let width_context = DimensionContext { - dpi: crate::DEFAULT_DPI as f32, - pixel_max: 65535., - pixel_cell: 65535., - }; - let height_context = DimensionContext { - dpi: crate::DEFAULT_DPI as f32, - pixel_max: 65535., - pixel_cell: 65535., - }; - let width = geometry.width.evaluate_as_pixels(width_context) as usize; - let height = geometry.height.evaluate_as_pixels(height_context) as usize; + let ResolvedGeometry { + x: _, + y: _, + width, + height, + } = conn.resolve_geometry(geometry); let dimensions = Dimensions { pixel_width: width,