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). |
8 | use 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)] |
17 | pub struct VideoMode { |
18 | pub(crate) video_mode: platform_impl::VideoMode, |
19 | } |
20 | |
21 | impl 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 | |
27 | impl PartialOrd for VideoMode { |
28 | fn partial_cmp(&self, other: &VideoMode) -> Option<std::cmp::Ordering> { |
29 | Some(self.cmp(other)) |
30 | } |
31 | } |
32 | |
33 | impl 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 | |
48 | impl 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 | |
84 | impl 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)] |
103 | pub struct MonitorHandle { |
104 | pub(crate) inner: platform_impl::MonitorHandle, |
105 | } |
106 | |
107 | impl 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 | |