diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab20df4..e4af8607 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - **Breaking:** The entire API for sizes, positions, etc. has changed. In the majority of cases, winit produces and consumes positions and sizes as `LogicalPosition` and `LogicalSize`, respectively. The notable exception is `MonitorId` methods, which deal in `PhysicalPosition` and `PhysicalSize`. See the documentation for specifics and explanations of the types. Additionally, winit automatically conserves logical size when the DPI factor changes. - **Breaking:** All deprecated methods have been removed. For `Window::platform_display` and `Window::platform_window`, switch to the appropriate platform-specific `WindowExt` methods. For `Window::get_inner_size_points` and `Window::get_inner_size_pixels`, use the `LogicalSize` returned by `Window::get_inner_size` and convert as needed. - HiDPI support for Wayland. +- `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow. +- `AvailableMonitorsIter` now implements `Debug`. # Version 0.15.1 (2018-06-13) diff --git a/examples/monitor_list.rs b/examples/monitor_list.rs new file mode 100644 index 00000000..e40ac309 --- /dev/null +++ b/examples/monitor_list.rs @@ -0,0 +1,7 @@ +extern crate winit; + +fn main() { + let event_loop = winit::EventsLoop::new(); + let window = winit::WindowBuilder::new().build(&event_loop).unwrap(); + println!("{:#?}\nPrimary: {:#?}", window.get_available_monitors(), window.get_primary_monitor()); +} diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index 66724b4b..94c8182d 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -385,6 +385,18 @@ impl Window { RootMonitorId { inner: MonitorId } } + #[inline] + pub fn get_available_monitors(&self) -> VecDeque { + let mut rb = VecDeque::with_capacity(1); + rb.push_back(MonitorId); + rb + } + + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + MonitorId + } + #[inline] pub fn id(&self) -> WindowId { WindowId diff --git a/src/platform/emscripten/mod.rs b/src/platform/emscripten/mod.rs index b31ad00d..41da4213 100644 --- a/src/platform/emscripten/mod.rs +++ b/src/platform/emscripten/mod.rs @@ -9,7 +9,8 @@ use std::os::raw::{c_char, c_void, c_double, c_ulong, c_int}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Mutex, Arc}; -use {LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; +use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; +use window::MonitorId as RootMonitorId; const DOCUMENT_NAME: &'static str = "#document\0"; @@ -582,8 +583,20 @@ impl Window { } #[inline] - pub fn get_current_monitor(&self) -> ::MonitorId { - ::MonitorId{inner: MonitorId} + pub fn get_current_monitor(&self) -> RootMonitorId { + RootMonitorId { inner: MonitorId } + } + + #[inline] + pub fn get_available_monitors(&self) -> VecDeque { + let mut list = VecDeque::with_capacity(1); + list.push_back(MonitorId); + list + } + + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + MonitorId } } diff --git a/src/platform/ios/mod.rs b/src/platform/ios/mod.rs index bf06f4b3..96f9aef0 100644 --- a/src/platform/ios/mod.rs +++ b/src/platform/ios/mod.rs @@ -447,6 +447,18 @@ impl Window { RootMonitorId { inner: MonitorId } } + #[inline] + pub fn get_available_monitors(&self) -> VecDeque { + let mut rb = VecDeque::with_capacity(1); + rb.push_back(MonitorId); + rb + } + + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + MonitorId + } + #[inline] pub fn id(&self) -> WindowId { WindowId diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index e49c688d..83f0869d 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -325,8 +325,30 @@ impl Window { #[inline] pub fn get_current_monitor(&self) -> RootMonitorId { match self { - &Window::X(ref w) => RootMonitorId{inner: MonitorId::X(w.get_current_monitor())}, - &Window::Wayland(ref w) => RootMonitorId{inner: MonitorId::Wayland(w.get_current_monitor())}, + &Window::X(ref window) => RootMonitorId { inner: MonitorId::X(window.get_current_monitor()) }, + &Window::Wayland(ref window) => RootMonitorId { inner: MonitorId::Wayland(window.get_current_monitor()) }, + } + } + + #[inline] + pub fn get_available_monitors(&self) -> VecDeque { + match self { + &Window::X(ref window) => window.get_available_monitors() + .into_iter() + .map(MonitorId::X) + .collect(), + &Window::Wayland(ref window) => window.get_available_monitors() + .into_iter() + .map(MonitorId::Wayland) + .collect(), + } + } + + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + match self { + &Window::X(ref window) => MonitorId::X(window.get_primary_monitor()), + &Window::Wayland(ref window) => MonitorId::Wayland(window.get_primary_monitor()), } } } diff --git a/src/platform/linux/wayland/event_loop.rs b/src/platform/linux/wayland/event_loop.rs index 99a34cac..9efa307e 100644 --- a/src/platform/linux/wayland/event_loop.rs +++ b/src/platform/linux/wayland/event_loop.rs @@ -199,27 +199,11 @@ impl EventsLoop { } pub fn get_primary_monitor(&self) -> MonitorId { - self.env.outputs.with_all(|list| { - if let Some(&(_, ref proxy, _)) = list.first() { - MonitorId { - proxy: proxy.clone(), - mgr: self.env.outputs.clone(), - } - } else { - panic!("No monitor is available.") - } - }) + get_primary_monitor(&self.env.outputs) } pub fn get_available_monitors(&self) -> VecDeque { - self.env.outputs.with_all(|list| { - list.iter() - .map(|&(_, ref proxy, _)| MonitorId { - proxy: proxy.clone(), - mgr: self.env.outputs.clone(), - }) - .collect() - }) + get_available_monitors(&self.env.outputs) } } @@ -494,3 +478,27 @@ impl MonitorId { .unwrap_or(1) } } + +pub fn get_primary_monitor(outputs: &OutputMgr) -> MonitorId { + outputs.with_all(|list| { + if let Some(&(_, ref proxy, _)) = list.first() { + MonitorId { + proxy: proxy.clone(), + mgr: outputs.clone(), + } + } else { + panic!("No monitor is available.") + } + }) +} + +pub fn get_available_monitors(outputs: &OutputMgr) -> VecDeque { + outputs.with_all(|list| { + list.iter() + .map(|&(_, ref proxy, _)| MonitorId { + proxy: proxy.clone(), + mgr: outputs.clone(), + }) + .collect() + }) +} diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index eddeae07..cf6b8fff 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -1,3 +1,4 @@ +use std::collections::VecDeque; use std::sync::{Arc, Mutex, Weak}; use {CreationError, CursorState, MouseCursor, WindowAttributes, LogicalPosition, LogicalSize}; @@ -9,13 +10,16 @@ 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_surface::RequestsTrait as SurfaceRequests; +use sctk::output::OutputMgr; use super::{make_wid, EventsLoop, MonitorId, WindowId}; +use platform::platform::wayland::event_loop::{get_available_monitors, get_primary_monitor}; pub struct Window { surface: Proxy, frame: Arc>>, - monitors: Arc>, + monitors: Arc>, // Monitors this window is currently on + outputs: OutputMgr, // Access to info for all monitors size: Arc>, kill_switch: (Arc>, Arc>), display: Arc, @@ -153,6 +157,7 @@ impl Window { surface: surface, frame: frame, monitors: monitor_list, + outputs: evlp.env.outputs.clone(), size: size, kill_switch: (kill_switch, evlp.cleanup_needed.clone()), need_frame_refresh: need_frame_refresh, @@ -297,6 +302,14 @@ impl Window { let guard = self.monitors.lock().unwrap(); guard.monitors.last().unwrap().clone() } + + pub fn get_available_monitors(&self) -> VecDeque { + get_available_monitors(&self.outputs) + } + + pub fn get_primary_monitor(&self) -> MonitorId { + get_primary_monitor(&self.outputs) + } } impl Drop for Window { diff --git a/src/platform/linux/x11/window.rs b/src/platform/linux/x11/window.rs index e4d0ef9f..e2a2fd23 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -503,6 +503,14 @@ impl UnownedWindow { }) } + pub fn get_available_monitors(&self) -> Vec { + self.xconn.get_available_monitors() + } + + pub fn get_primary_monitor(&self) -> X11MonitorId { + self.xconn.get_primary_monitor() + } + fn set_maximized_inner(&self, maximized: bool) -> util::Flusher { let horz_atom = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_STATE_MAXIMIZED_HORZ\0") }; let vert_atom = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_STATE_MAXIMIZED_VERT\0") }; diff --git a/src/platform/macos/monitor.rs b/src/platform/macos/monitor.rs index 0e8c2461..c8786f9d 100644 --- a/src/platform/macos/monitor.rs +++ b/src/platform/macos/monitor.rs @@ -8,26 +8,37 @@ use core_graphics::display::{CGDirectDisplayID, CGDisplay, CGDisplayBounds}; use {PhysicalPosition, PhysicalSize}; use super::EventsLoop; -use super::window::IdRef; +use super::window::{IdRef, Window2}; #[derive(Clone, PartialEq)] pub struct MonitorId(CGDirectDisplayID); -impl EventsLoop { - pub fn get_available_monitors(&self) -> VecDeque { - let mut monitors = VecDeque::new(); - if let Ok(displays) = CGDisplay::active_displays() { - for d in displays { - monitors.push_back(MonitorId(d)); - } +fn get_available_monitors() -> VecDeque { + if let Ok(displays) = CGDisplay::active_displays() { + let mut monitors = VecDeque::with_capacity(displays.len()); + for d in displays { + monitors.push_back(MonitorId(d)); } monitors + } else { + VecDeque::with_capacity(0) + } +} + +pub fn get_primary_monitor() -> MonitorId { + let id = MonitorId(CGDisplay::main().id); + id +} + +impl EventsLoop { + #[inline] + pub fn get_available_monitors(&self) -> VecDeque { + get_available_monitors() } #[inline] pub fn get_primary_monitor(&self) -> MonitorId { - let id = MonitorId(CGDisplay::main().id); - id + get_primary_monitor() } pub fn make_monitor_from_display(id: CGDirectDisplayID) -> MonitorId { @@ -36,6 +47,18 @@ impl EventsLoop { } } +impl Window2 { + #[inline] + pub fn get_available_monitors(&self) -> VecDeque { + get_available_monitors() + } + + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + get_primary_monitor() + } +} + impl fmt::Debug for MonitorId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[derive(Debug)] diff --git a/src/platform/windows/monitor.rs b/src/platform/windows/monitor.rs index 83d54f57..4ff90d21 100644 --- a/src/platform/windows/monitor.rs +++ b/src/platform/windows/monitor.rs @@ -5,9 +5,10 @@ use winapi::um::winuser; use std::{mem, ptr}; use std::collections::VecDeque; -use {PhysicalPosition, PhysicalSize}; use super::{EventsLoop, util}; +use dpi::{PhysicalPosition, PhysicalSize}; use platform::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi}; +use platform::platform::window::Window; /// Win32 implementation of the main `MonitorId` object. #[derive(Debug, Clone)] @@ -48,19 +49,31 @@ unsafe extern "system" fn monitor_enum_proc( TRUE // continue enumeration } +fn get_available_monitors() -> VecDeque { + let mut monitors: VecDeque = VecDeque::new(); + unsafe { + winuser::EnumDisplayMonitors( + ptr::null_mut(), + ptr::null_mut(), + Some(monitor_enum_proc), + &mut monitors as *mut _ as LPARAM, + ); + } + monitors +} + +fn get_primary_monitor() -> MonitorId { + const ORIGIN: POINT = POINT { x: 0, y: 0 }; + let hmonitor = unsafe { + winuser::MonitorFromPoint(ORIGIN, winuser::MONITOR_DEFAULTTOPRIMARY) + }; + MonitorId::from_hmonitor(hmonitor) +} + impl EventsLoop { // TODO: Investigate opportunities for caching pub fn get_available_monitors(&self) -> VecDeque { - let mut monitors: VecDeque = VecDeque::new(); - unsafe { - winuser::EnumDisplayMonitors( - ptr::null_mut(), - ptr::null_mut(), - Some(monitor_enum_proc), - &mut monitors as *mut _ as LPARAM, - ); - } - monitors + get_available_monitors() } pub fn get_current_monitor(hwnd: HWND) -> MonitorId { @@ -71,11 +84,17 @@ impl EventsLoop { } pub fn get_primary_monitor(&self) -> MonitorId { - const ORIGIN: POINT = POINT { x: 0, y: 0 }; - let hmonitor = unsafe { - winuser::MonitorFromPoint(ORIGIN, winuser::MONITOR_DEFAULTTOPRIMARY) - }; - MonitorId::from_hmonitor(hmonitor) + get_primary_monitor() + } +} + +impl Window { + pub fn get_available_monitors(&self) -> VecDeque { + get_available_monitors() + } + + pub fn get_primary_monitor(&self) -> MonitorId { + get_primary_monitor() } } diff --git a/src/window.rs b/src/window.rs index 0fb2c4d2..f545f4ce 100644 --- a/src/window.rs +++ b/src/window.rs @@ -384,6 +384,23 @@ impl Window { self.window.get_current_monitor() } + /// Returns the list of all the monitors available on the system. + /// + /// This is the same as `EventsLoop::get_available_monitors`, and is provided for convenience. + #[inline] + pub fn get_available_monitors(&self) -> AvailableMonitorsIter { + let data = self.window.get_available_monitors(); + AvailableMonitorsIter { data: data.into_iter() } + } + + /// Returns the primary monitor of the system. + /// + /// This is the same as `EventsLoop::get_primary_monitor`, and is provided for convenience. + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + MonitorId { inner: self.window.get_primary_monitor() } + } + #[inline] pub fn id(&self) -> WindowId { WindowId(self.window.id()) @@ -393,6 +410,7 @@ impl Window { /// An iterator for the list of available monitors. // Implementation note: we retrieve the list once, then serve each element by one by one. // This may change in the future. +#[derive(Debug)] pub struct AvailableMonitorsIter { pub(crate) data: VecDequeIter, }