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//! - [`ActiveEventLoop::available_monitors`][crate::event_loop::ActiveEventLoop::available_monitors].
7//! - [`Window::available_monitors`][crate::window::Window::available_monitors].
8use std::num::{NonZeroU16, NonZeroU32};
9
10use crate::dpi::{PhysicalPosition, PhysicalSize};
11use crate::platform_impl;
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 VideoModeHandle {
18    pub(crate) video_mode: platform_impl::VideoModeHandle,
19}
20
21impl std::fmt::Debug for VideoModeHandle {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        self.video_mode.fmt(f)
24    }
25}
26
27impl PartialOrd for VideoModeHandle {
28    fn partial_cmp(&self, other: &VideoModeHandle) -> Option<std::cmp::Ordering> {
29        Some(self.cmp(other))
30    }
31}
32
33impl Ord for VideoModeHandle {
34    fn cmp(&self, other: &VideoModeHandle) -> 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 VideoModeHandle {
49    /// Returns the resolution of this video mode. This **must not** be used to create your
50    /// rendering surface. Use [`Window::surface_size()`] instead.
51    ///
52    /// [`Window::surface_size()`]: crate::window::Window::surface_size
53    #[inline]
54    pub fn size(&self) -> PhysicalSize<u32> {
55        self.video_mode.size()
56    }
57
58    /// Returns the bit depth of this video mode, as in how many bits you have
59    /// available per color. This is generally 24 bits or 32 bits on modern
60    /// systems, depending on whether the alpha channel is counted or not.
61    #[inline]
62    pub fn bit_depth(&self) -> Option<NonZeroU16> {
63        self.video_mode.bit_depth()
64    }
65
66    /// Returns the refresh rate of this video mode in mHz.
67    #[inline]
68    pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
69        self.video_mode.refresh_rate_millihertz()
70    }
71
72    /// Returns the monitor that this video mode is valid for. Each monitor has
73    /// a separate set of valid video modes.
74    #[inline]
75    pub fn monitor(&self) -> MonitorHandle {
76        MonitorHandle { inner: self.video_mode.monitor() }
77    }
78}
79
80impl std::fmt::Display for VideoModeHandle {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        write!(
83            f,
84            "{}x{} {}{}",
85            self.size().width,
86            self.size().height,
87            self.refresh_rate_millihertz().map(|rate| format!("@ {rate} mHz ")).unwrap_or_default(),
88            self.bit_depth().map(|bit_depth| format!("({bit_depth} bpp)")).unwrap_or_default(),
89        )
90    }
91}
92
93/// Handle to a monitor.
94///
95/// Allows you to retrieve information about a given monitor and can be used in [`Window`] creation.
96///
97/// ## Platform-specific
98///
99/// **Web:** A [`MonitorHandle`] created without
100#[cfg_attr(
101    any(web_platform, docsrs),
102    doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
103)]
104#[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
105/// will always represent the current monitor the browser window is in instead of a specific
106/// monitor. See
107#[cfg_attr(
108    any(web_platform, docsrs),
109    doc = "[`MonitorHandleExtWeb::is_detailed()`][crate::platform::web::MonitorHandleExtWeb::is_detailed]"
110)]
111#[cfg_attr(not(any(web_platform, docsrs)), doc = "`MonitorHandleExtWeb::is_detailed()`")]
112/// to check.
113///
114/// [`Window`]: crate::window::Window
115#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
116pub struct MonitorHandle {
117    pub(crate) inner: platform_impl::MonitorHandle,
118}
119
120impl std::fmt::Debug for MonitorHandle {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        self.inner.fmt(f)
123    }
124}
125
126impl MonitorHandle {
127    /// Returns a human-readable name of the monitor.
128    ///
129    /// Returns `None` if the monitor doesn't exist anymore.
130    ///
131    /// ## Platform-specific
132    ///
133    /// **Web:** Always returns [`None`] without
134    #[cfg_attr(
135        any(web_platform, docsrs),
136        doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
137    )]
138    #[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
139    #[inline]
140    pub fn name(&self) -> Option<String> {
141        self.inner.name()
142    }
143
144    /// Returns the top-left corner position of the monitor relative to the larger full
145    /// screen area.
146    ///
147    /// ## Platform-specific
148    ///
149    /// **Web:** Always returns [`None`] without
150    #[cfg_attr(
151        any(web_platform, docsrs),
152        doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
153    )]
154    #[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
155    #[inline]
156    pub fn position(&self) -> Option<PhysicalPosition<i32>> {
157        self.inner.position()
158    }
159
160    /// Returns the scale factor of the underlying monitor. To map logical pixels to physical
161    /// pixels and vice versa, use [`Window::scale_factor`].
162    ///
163    /// See the [`dpi`] module for more information.
164    ///
165    /// ## Platform-specific
166    ///
167    /// - **X11:** Can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
168    /// - **Wayland:** May differ from [`Window::scale_factor`].
169    /// - **Android:** Always returns 1.0.
170    /// - **Web:** Always returns `0.0` without
171    #[cfg_attr(
172        any(web_platform, docsrs),
173        doc = "  [detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
174    )]
175    #[cfg_attr(not(any(web_platform, docsrs)), doc = "  detailed monitor permissions.")]
176    ///
177    #[rustfmt::skip]
178    /// [`Window::scale_factor`]: crate::window::Window::scale_factor
179    #[inline]
180    pub fn scale_factor(&self) -> f64 {
181        self.inner.scale_factor()
182    }
183
184    /// Returns the currently active video mode of this monitor.
185    #[inline]
186    pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
187        self.inner.current_video_mode().map(|video_mode| VideoModeHandle { video_mode })
188    }
189
190    /// Returns all fullscreen video modes supported by this monitor.
191    #[inline]
192    pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
193        self.inner.video_modes().map(|video_mode| VideoModeHandle { video_mode })
194    }
195}