use std::borrow::Cow;
use std::fmt;
use std::num::{NonZeroU16, NonZeroU32};
use std::ops::Deref;
use std::sync::Arc;
use dpi::{PhysicalPosition, PhysicalSize};
use crate::as_any::AsAny;
#[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 {}
pub trait MonitorHandleProvider: AsAny + fmt::Debug + Send + Sync {
fn id(&self) -> u128;
fn native_id(&self) -> u64;
fn name(&self) -> Option<Cow<'_, str>>;
fn position(&self) -> Option<PhysicalPosition<i32>>;
fn scale_factor(&self) -> f64;
fn current_video_mode(&self) -> Option<VideoMode>;
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);
#[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 }
}
pub fn size(&self) -> PhysicalSize<u32> {
self.size
}
pub fn bit_depth(&self) -> Option<NonZeroU16> {
self.bit_depth
}
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(),
)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Fullscreen {
Exclusive(MonitorHandle, VideoMode),
Borderless(Option<MonitorHandle>),
}