mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-29 04:40:04 -04:00
Trait upcasting (rust-lang/rust#65991) is stable since Rust 1.86, which is already the MSRV, so dyn trait objects coerce to dyn Any directly. Traits that needed AsAny now list Any as their supertrait, and the as_any module is renamed to casting as only the impl_dyn_casting macro remains.
192 lines
6.4 KiB
Rust
192 lines
6.4 KiB
Rust
//! Types useful for interacting with a user's monitors.
|
|
//!
|
|
//! If you want to get basic information about a monitor, you can use the
|
|
//! [`MonitorHandle`] type. This is retrieved from one of the following
|
|
//! methods, which return an iterator of [`MonitorHandle`]:
|
|
//! - [`ActiveEventLoop::available_monitors`][crate::event_loop::ActiveEventLoop::available_monitors].
|
|
//! - [`Window::available_monitors`][crate::window::Window::available_monitors].
|
|
use std::any::Any;
|
|
use std::borrow::Cow;
|
|
use std::fmt;
|
|
use std::num::{NonZeroU16, NonZeroU32};
|
|
use std::ops::Deref;
|
|
use std::sync::Arc;
|
|
|
|
use dpi::{PhysicalPosition, PhysicalSize};
|
|
|
|
/// Handle to a monitor.
|
|
///
|
|
/// Allows you to retrieve basic information and metadata about a monitor.
|
|
///
|
|
/// Can be used in [`Window`] creation to place the window on a specific
|
|
/// monitor.
|
|
///
|
|
/// This can be retrieved from one of the following methods, which return an
|
|
/// iterator of [`MonitorHandle`]s:
|
|
/// - [`ActiveEventLoop::available_monitors`](crate::event_loop::ActiveEventLoop::available_monitors).
|
|
/// - [`Window::available_monitors`](crate::window::Window::available_monitors).
|
|
///
|
|
/// ## Platform-specific
|
|
///
|
|
/// **Web:** A [`MonitorHandle`] created without `detailed monitor permissions`
|
|
/// will always represent the current monitor the browser window is in instead of a specific
|
|
/// monitor.
|
|
///
|
|
/// [`Window`]: crate::window::Window
|
|
#[derive(Debug, Clone)]
|
|
pub struct MonitorHandle(pub Arc<dyn MonitorHandleProvider>);
|
|
|
|
impl Deref for MonitorHandle {
|
|
type Target = dyn MonitorHandleProvider;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
self.0.as_ref()
|
|
}
|
|
}
|
|
|
|
impl PartialEq for MonitorHandle {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.0.as_ref().eq(other.0.as_ref())
|
|
}
|
|
}
|
|
|
|
impl Eq for MonitorHandle {}
|
|
|
|
/// Provider of the [`MonitorHandle`].
|
|
pub trait MonitorHandleProvider: Any + fmt::Debug + Send + Sync {
|
|
/// Identifier for this monitor.
|
|
///
|
|
/// The representation of this modifier is not guaranteed and should be used only to compare
|
|
/// monitors.
|
|
fn id(&self) -> u128;
|
|
|
|
/// Native platform identifier of this monitor.
|
|
///
|
|
/// # Platform-specific
|
|
///
|
|
/// - **Windows**: This is `HMONITOR`.
|
|
/// - **macOS**: This is `CGDirectDisplayID`.
|
|
/// - **iOS**: This is `UIScreen*`.
|
|
/// - **Wayland**: This is the ID of the `wl_output` device.
|
|
/// - **X11**: This is the ID of the CRTC.
|
|
/// - **Web**: This is an internal ID not meant for consumption.
|
|
fn native_id(&self) -> u64;
|
|
|
|
/// Returns a human-readable name of the monitor.
|
|
///
|
|
/// Returns `None` if the monitor doesn't exist anymore or the name couldn't be obtained.
|
|
///
|
|
///
|
|
/// ## Platform-specific
|
|
///
|
|
/// **Web:** Always returns [`None`] without `detailed monitor permissions`.
|
|
fn name(&self) -> Option<Cow<'_, str>>;
|
|
|
|
/// Returns the top-left corner position of the monitor in desktop coordinates.
|
|
///
|
|
/// This position is in the same coordinate system as [`Window::outer_position`].
|
|
///
|
|
/// [`Window::outer_position`]: crate::window::Window::outer_position
|
|
///
|
|
/// ## Platform-specific
|
|
///
|
|
/// **Web:** Always returns [`None`] without `detailed monitor permissions`.
|
|
fn position(&self) -> Option<PhysicalPosition<i32>>;
|
|
|
|
/// Returns the scale factor of the underlying monitor. To map logical pixels to physical
|
|
/// pixels and vice versa, use [`Window::scale_factor`].
|
|
///
|
|
/// See the [`dpi`] module for more information.
|
|
///
|
|
/// - **Wayland:** May differ from [`Window::scale_factor`].
|
|
/// - **Web:** Always returns `0.0` without `detailed_monitor_permissions`.
|
|
///
|
|
/// [`Window::scale_factor`]: crate::window::Window::scale_factor
|
|
fn scale_factor(&self) -> f64;
|
|
|
|
fn current_video_mode(&self) -> Option<VideoMode>;
|
|
|
|
/// Returns all fullscreen video modes supported by this monitor.
|
|
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>>;
|
|
}
|
|
|
|
impl PartialEq for dyn MonitorHandleProvider + '_ {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.id() == other.id()
|
|
}
|
|
}
|
|
|
|
impl Eq for dyn MonitorHandleProvider + '_ {}
|
|
|
|
impl_dyn_casting!(MonitorHandleProvider);
|
|
|
|
/// Describes a fullscreen video mode of a monitor.
|
|
///
|
|
/// Can be acquired with [`MonitorHandleProvider::video_modes`].
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
pub struct VideoMode {
|
|
pub(crate) size: PhysicalSize<u32>,
|
|
pub(crate) bit_depth: Option<NonZeroU16>,
|
|
pub(crate) refresh_rate_millihertz: Option<NonZeroU32>,
|
|
}
|
|
|
|
impl VideoMode {
|
|
pub fn new(
|
|
size: PhysicalSize<u32>,
|
|
bit_depth: Option<NonZeroU16>,
|
|
refresh_rate_millihertz: Option<NonZeroU32>,
|
|
) -> Self {
|
|
Self { size, bit_depth, refresh_rate_millihertz }
|
|
}
|
|
|
|
/// Returns the resolution of this video mode. This **must not** be used to create your
|
|
/// rendering surface. Use [`Window::surface_size()`] instead.
|
|
///
|
|
/// [`Window::surface_size()`]: crate::window::Window::surface_size
|
|
pub fn size(&self) -> PhysicalSize<u32> {
|
|
self.size
|
|
}
|
|
|
|
/// Returns the bit depth of this video mode, as in how many bits you have
|
|
/// available per color. This is generally 24 bits or 32 bits on modern
|
|
/// systems, depending on whether the alpha channel is counted or not.
|
|
///
|
|
/// # Platform-specific
|
|
///
|
|
/// - **macOS**: Video modes do not control the bit depth of the monitor, so this often defaults
|
|
/// to 32.
|
|
/// - **iOS**: Always returns `None`.
|
|
/// - **Wayland**: Always returns `None`.
|
|
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
|
self.bit_depth
|
|
}
|
|
|
|
/// Returns the refresh rate of this video mode in mHz.
|
|
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
|
self.refresh_rate_millihertz
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for VideoMode {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}x{} {}{}",
|
|
self.size.width,
|
|
self.size.height,
|
|
self.refresh_rate_millihertz.map(|rate| format!("@ {rate} mHz ")).unwrap_or_default(),
|
|
self.bit_depth.map(|bit_depth| format!("({bit_depth} bpp)")).unwrap_or_default(),
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Fullscreen modes.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
#[non_exhaustive]
|
|
pub enum Fullscreen {
|
|
Exclusive(MonitorHandle, VideoMode),
|
|
|
|
/// Providing `None` to `Borderless` will fullscreen on the current monitor.
|
|
Borderless(Option<MonitorHandle>),
|
|
}
|