floem_winit/
monitor.rs

1//! Types useful for interacting with a user's monitors.
2//!
3//! If you want to get basic information about a monitor, you can use the
4//! [`MonitorHandle`] type. This is retrieved from one of the following
5//! methods, which return an iterator of [`MonitorHandle`]:
6//! - [`EventLoopWindowTarget::available_monitors`](crate::event_loop::EventLoopWindowTarget::available_monitors).
7//! - [`Window::available_monitors`](crate::window::Window::available_monitors).
8use crate::{
9    dpi::{PhysicalPosition, PhysicalSize},
10    platform_impl,
11};
12
13/// Describes a fullscreen video mode of a monitor.
14///
15/// Can be acquired with [`MonitorHandle::video_modes`].
16#[derive(Clone, PartialEq, Eq, Hash)]
17pub struct VideoMode {
18    pub(crate) video_mode: platform_impl::VideoMode,
19}
20
21impl std::fmt::Debug for VideoMode {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        self.video_mode.fmt(f)
24    }
25}
26
27impl PartialOrd for VideoMode {
28    fn partial_cmp(&self, other: &VideoMode) -> Option<std::cmp::Ordering> {
29        Some(self.cmp(other))
30    }
31}
32
33impl Ord for VideoMode {
34    fn cmp(&self, other: &VideoMode) -> std::cmp::Ordering {
35        self.monitor().cmp(&other.monitor()).then(
36            self.size()
37                .cmp(&other.size())
38                .then(
39                    self.refresh_rate_millihertz()
40                        .cmp(&other.refresh_rate_millihertz())
41                        .then(self.bit_depth().cmp(&other.bit_depth())),
42                )
43                .reverse(),
44        )
45    }
46}
47
48impl VideoMode {
49    /// Returns the resolution of this video mode.
50    #[inline]
51    pub fn size(&self) -> PhysicalSize<u32> {
52        self.video_mode.size()
53    }
54
55    /// Returns the bit depth of this video mode, as in how many bits you have
56    /// available per color. This is generally 24 bits or 32 bits on modern
57    /// systems, depending on whether the alpha channel is counted or not.
58    ///
59    /// ## Platform-specific
60    ///
61    /// - **Wayland / Orbital:** Always returns 32.
62    /// - **iOS:** Always returns 32.
63    #[inline]
64    pub fn bit_depth(&self) -> u16 {
65        self.video_mode.bit_depth()
66    }
67
68    /// Returns the refresh rate of this video mode in mHz.
69    #[inline]
70    pub fn refresh_rate_millihertz(&self) -> u32 {
71        self.video_mode.refresh_rate_millihertz()
72    }
73
74    /// Returns the monitor that this video mode is valid for. Each monitor has
75    /// a separate set of valid video modes.
76    #[inline]
77    pub fn monitor(&self) -> MonitorHandle {
78        MonitorHandle {
79            inner: self.video_mode.monitor(),
80        }
81    }
82}
83
84impl std::fmt::Display for VideoMode {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        write!(
87            f,
88            "{}x{} @ {} mHz ({} bpp)",
89            self.size().width,
90            self.size().height,
91            self.refresh_rate_millihertz(),
92            self.bit_depth()
93        )
94    }
95}
96
97/// Handle to a monitor.
98///
99/// Allows you to retrieve information about a given monitor and can be used in [`Window`] creation.
100///
101/// [`Window`]: crate::window::Window
102#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
103pub struct MonitorHandle {
104    pub(crate) inner: platform_impl::MonitorHandle,
105}
106
107impl MonitorHandle {
108    /// Returns a human-readable name of the monitor.
109    ///
110    /// Returns `None` if the monitor doesn't exist anymore.
111    #[inline]
112    pub fn name(&self) -> Option<String> {
113        self.inner.name()
114    }
115
116    /// Returns the monitor's resolution.
117    #[inline]
118    pub fn size(&self) -> PhysicalSize<u32> {
119        self.inner.size()
120    }
121
122    /// Returns the top-left corner position of the monitor relative to the larger full
123    /// screen area.
124    #[inline]
125    pub fn position(&self) -> PhysicalPosition<i32> {
126        self.inner.position()
127    }
128
129    /// The monitor refresh rate used by the system.
130    ///
131    /// Return `Some` if succeed, or `None` if failed, which usually happens when the monitor
132    /// the window is on is removed.
133    ///
134    /// When using exclusive fullscreen, the refresh rate of the [`VideoMode`] that was used to
135    /// enter fullscreen should be used instead.
136    #[inline]
137    pub fn refresh_rate_millihertz(&self) -> Option<u32> {
138        self.inner.refresh_rate_millihertz()
139    }
140
141    /// Returns the scale factor of the underlying monitor. To map logical pixels to physical
142    /// pixels and vice versa, use [`Window::scale_factor`].
143    ///
144    /// See the [`dpi`](crate::dpi) module for more information.
145    ///
146    /// ## Platform-specific
147    ///
148    /// - **X11:** Can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
149    /// - **Wayland:** May differ from [`Window::scale_factor`].
150    /// - **Android:** Always returns 1.0.
151    ///
152    /// [`Window::scale_factor`]: crate::window::Window::scale_factor
153    #[inline]
154    pub fn scale_factor(&self) -> f64 {
155        self.inner.scale_factor()
156    }
157
158    /// Returns all fullscreen video modes supported by this monitor.
159    ///
160    /// ## Platform-specific
161    ///
162    /// - **Web:** Always returns an empty iterator
163    #[inline]
164    pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
165        self.inner
166            .video_modes()
167            .map(|video_mode| VideoMode { video_mode })
168    }
169}