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}
170