Various Monitor/VideoModeHandle methods now return an Option
`VideoModeHandle::refresh_rate_millihertz()` and `bit_depth()` now return a `Option<NonZero*>`. `MonitorHandle::position()` now returns an `Option`. On Orbital `MonitorHandle::name()` now returns `None` instead of a dummy name.
This commit is contained in:
parent
0ffcfd8a3a
commit
58142680ce
15 changed files with 259 additions and 195 deletions
|
|
@ -1,9 +1,11 @@
|
|||
use std::cell::{OnceCell, Ref, RefCell};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::future::Future;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{self, Once};
|
||||
use std::mem;
|
||||
use std::num::{NonZeroU16, NonZeroU32};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::pin::Pin;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
|
@ -31,7 +33,7 @@ use crate::platform::web::{
|
|||
MonitorPermissionError, Orientation, OrientationData, OrientationLock, OrientationLockError,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Eq)]
|
||||
#[derive(Clone, Eq)]
|
||||
pub struct MonitorHandle {
|
||||
/// [`None`] means [`web_sys::Screen`], which is always the same.
|
||||
id: Option<u64>,
|
||||
|
|
@ -45,30 +47,15 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
self.inner.queue(|inner| match &inner.screen {
|
||||
Screen::Screen(_) => 0.,
|
||||
Screen::Detailed { screen, .. } => screen.device_pixel_ratio(),
|
||||
})
|
||||
self.inner.queue(|inner| inner.scale_factor())
|
||||
}
|
||||
|
||||
pub fn position(&self) -> PhysicalPosition<i32> {
|
||||
self.inner.queue(|inner| {
|
||||
if let Screen::Detailed { screen, .. } = &inner.screen {
|
||||
PhysicalPosition::new(screen.left(), screen.top())
|
||||
} else {
|
||||
PhysicalPosition::default()
|
||||
}
|
||||
})
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
self.inner.queue(|inner| inner.position())
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<String> {
|
||||
self.inner.queue(|inner| {
|
||||
if let Screen::Detailed { screen, .. } = &inner.screen {
|
||||
Some(screen.label())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
self.inner.queue(|inner| inner.name())
|
||||
}
|
||||
|
||||
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||
|
|
@ -80,36 +67,7 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
pub fn orientation(&self) -> OrientationData {
|
||||
self.inner.queue(|inner| {
|
||||
let orientation = inner.orientation();
|
||||
let angle = orientation.angle().unwrap();
|
||||
|
||||
match orientation.type_().unwrap() {
|
||||
OrientationType::LandscapePrimary => OrientationData {
|
||||
orientation: Orientation::Landscape,
|
||||
flipped: false,
|
||||
natural: angle == 0,
|
||||
},
|
||||
OrientationType::LandscapeSecondary => OrientationData {
|
||||
orientation: Orientation::Landscape,
|
||||
flipped: true,
|
||||
natural: angle == 180,
|
||||
},
|
||||
OrientationType::PortraitPrimary => OrientationData {
|
||||
orientation: Orientation::Portrait,
|
||||
flipped: false,
|
||||
natural: angle == 0,
|
||||
},
|
||||
OrientationType::PortraitSecondary => OrientationData {
|
||||
orientation: Orientation::Portrait,
|
||||
flipped: true,
|
||||
natural: angle == 180,
|
||||
},
|
||||
_ => {
|
||||
unreachable!("found unrecognized orientation: {}", orientation.type_string())
|
||||
},
|
||||
}
|
||||
})
|
||||
self.inner.queue(|inner| inner.orientation())
|
||||
}
|
||||
|
||||
pub fn request_lock(&self, orientation_lock: OrientationLock) -> OrientationLockFuture {
|
||||
|
|
@ -126,7 +84,7 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
let future =
|
||||
JsFuture::from(inner.orientation().lock(orientation_lock.to_js()).unwrap());
|
||||
JsFuture::from(inner.orientation_raw().lock(orientation_lock.to_js()).unwrap());
|
||||
let notifier = Notifier::new();
|
||||
let notified = notifier.notified();
|
||||
|
||||
|
|
@ -151,22 +109,16 @@ impl MonitorHandle {
|
|||
return Err(OrientationLockError::Unsupported);
|
||||
}
|
||||
|
||||
inner.orientation().unlock().map_err(OrientationLockError::from_js)
|
||||
inner.orientation_raw().unlock().map_err(OrientationLockError::from_js)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_internal(&self) -> Option<bool> {
|
||||
self.inner.queue(|inner| {
|
||||
if let Screen::Detailed { screen, .. } = &inner.screen {
|
||||
Some(screen.is_internal())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
self.inner.queue(|inner| inner.is_internal())
|
||||
}
|
||||
|
||||
pub fn is_detailed(&self) -> bool {
|
||||
self.inner.queue(|inner| matches!(inner.screen, Screen::Detailed { .. }))
|
||||
self.inner.queue(|inner| inner.is_detailed())
|
||||
}
|
||||
|
||||
pub(crate) fn detailed(
|
||||
|
|
@ -187,6 +139,31 @@ impl MonitorHandle {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for MonitorHandle {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let (name, position, scale_factor, orientation, is_internal, is_detailed) =
|
||||
self.inner.queue(|this| {
|
||||
(
|
||||
this.name(),
|
||||
this.position(),
|
||||
this.scale_factor(),
|
||||
this.orientation(),
|
||||
this.is_internal(),
|
||||
this.is_detailed(),
|
||||
)
|
||||
});
|
||||
|
||||
f.debug_struct("MonitorHandle")
|
||||
.field("name", &name)
|
||||
.field("position", &position)
|
||||
.field("scale_factor", &scale_factor)
|
||||
.field("orientation", &orientation)
|
||||
.field("is_internal", &is_internal)
|
||||
.field("is_detailed", &is_detailed)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for MonitorHandle {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state)
|
||||
|
|
@ -268,29 +245,19 @@ impl OrientationLockError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct VideoModeHandle(pub(super) MonitorHandle);
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub struct VideoModeHandle(MonitorHandle);
|
||||
|
||||
impl VideoModeHandle {
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
self.0.inner.queue(|inner| {
|
||||
let width = inner.screen.width().unwrap();
|
||||
let height = inner.screen.height().unwrap();
|
||||
|
||||
if let Some(Engine::Chromium) = inner.engine {
|
||||
PhysicalSize::new(width, height).cast()
|
||||
} else {
|
||||
LogicalSize::new(width, height)
|
||||
.to_physical(super::web_sys::scale_factor(&inner.window))
|
||||
}
|
||||
})
|
||||
self.0.inner.queue(|inner| inner.size())
|
||||
}
|
||||
|
||||
pub fn bit_depth(&self) -> u16 {
|
||||
self.0.inner.queue(|inner| inner.screen.color_depth().unwrap()).try_into().unwrap()
|
||||
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
self.0.inner.queue(|inner| inner.bit_depth())
|
||||
}
|
||||
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -299,6 +266,14 @@ impl VideoModeHandle {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for VideoModeHandle {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let (size, bit_depth) = self.0.inner.queue(|this| (this.size(), this.bit_depth()));
|
||||
|
||||
f.debug_struct("MonitorHandle").field("size", &size).field("bit_depth", &bit_depth).finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
window: WindowExt,
|
||||
engine: Option<Engine>,
|
||||
|
|
@ -311,12 +286,94 @@ impl Inner {
|
|||
Self { window, engine, screen, orientation: OnceCell::new() }
|
||||
}
|
||||
|
||||
fn orientation(&self) -> &ScreenOrientationExt {
|
||||
fn scale_factor(&self) -> f64 {
|
||||
match &self.screen {
|
||||
Screen::Screen(_) => 0.,
|
||||
Screen::Detailed { screen, .. } => screen.device_pixel_ratio(),
|
||||
}
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
if let Screen::Detailed { screen, .. } = &self.screen {
|
||||
Some(PhysicalPosition::new(screen.left(), screen.top()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<String> {
|
||||
if let Screen::Detailed { screen, .. } = &self.screen {
|
||||
Some(screen.label())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn orientation_raw(&self) -> &ScreenOrientationExt {
|
||||
self.orientation.get_or_init(|| self.screen.orientation().unchecked_into())
|
||||
}
|
||||
|
||||
fn orientation(&self) -> OrientationData {
|
||||
let orientation = self.orientation_raw();
|
||||
|
||||
let angle = orientation.angle().unwrap();
|
||||
|
||||
match orientation.type_().unwrap() {
|
||||
OrientationType::LandscapePrimary => OrientationData {
|
||||
orientation: Orientation::Landscape,
|
||||
flipped: false,
|
||||
natural: angle == 0,
|
||||
},
|
||||
OrientationType::LandscapeSecondary => OrientationData {
|
||||
orientation: Orientation::Landscape,
|
||||
flipped: true,
|
||||
natural: angle == 180,
|
||||
},
|
||||
OrientationType::PortraitPrimary => OrientationData {
|
||||
orientation: Orientation::Portrait,
|
||||
flipped: false,
|
||||
natural: angle == 0,
|
||||
},
|
||||
OrientationType::PortraitSecondary => OrientationData {
|
||||
orientation: Orientation::Portrait,
|
||||
flipped: true,
|
||||
natural: angle == 180,
|
||||
},
|
||||
_ => {
|
||||
unreachable!("found unrecognized orientation: {}", orientation.type_string())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn is_internal(&self) -> Option<bool> {
|
||||
if let Screen::Detailed { screen, .. } = &self.screen {
|
||||
Some(screen.is_internal())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn is_detailed(&self) -> bool {
|
||||
matches!(self.screen, Screen::Detailed { .. })
|
||||
}
|
||||
|
||||
fn size(&self) -> PhysicalSize<u32> {
|
||||
let width = self.screen.width().unwrap();
|
||||
let height = self.screen.height().unwrap();
|
||||
|
||||
if let Some(Engine::Chromium) = self.engine {
|
||||
PhysicalSize::new(width, height).cast()
|
||||
} else {
|
||||
LogicalSize::new(width, height).to_physical(super::web_sys::scale_factor(&self.window))
|
||||
}
|
||||
}
|
||||
|
||||
fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
NonZeroU16::new(self.screen.color_depth().unwrap().try_into().unwrap())
|
||||
}
|
||||
|
||||
fn has_lock_support(&self) -> bool {
|
||||
*HAS_LOCK_SUPPORT.get_or_init(|| !self.orientation().has_lock().is_undefined())
|
||||
*HAS_LOCK_SUPPORT.get_or_init(|| !self.orientation_raw().has_lock().is_undefined())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue