Add MonitorHandle::current_video_mode()
This commit is contained in:
parent
1168cd4113
commit
2e53533cc1
12 changed files with 167 additions and 79 deletions
|
|
@ -61,6 +61,7 @@ changelog entry.
|
||||||
the primary finger in a multi-touch interaction.
|
the primary finger in a multi-touch interaction.
|
||||||
- Implement `Clone`, `Copy`, `Debug`, `Deserialize`, `Eq`, `Hash`, `Ord`, `PartialEq`, `PartialOrd`
|
- Implement `Clone`, `Copy`, `Debug`, `Deserialize`, `Eq`, `Hash`, `Ord`, `PartialEq`, `PartialOrd`
|
||||||
and `Serialize` on many types.
|
and `Serialize` on many types.
|
||||||
|
- Add `MonitorHandle::current_video_mode()`.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,12 @@ impl MonitorHandle {
|
||||||
self.inner.scale_factor()
|
self.inner.scale_factor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the currently active video mode of this monitor.
|
||||||
|
#[inline]
|
||||||
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
|
self.inner.current_video_mode().map(|video_mode| VideoModeHandle { video_mode })
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns all fullscreen video modes supported by this monitor.
|
/// Returns all fullscreen video modes supported by this monitor.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||||
|
|
|
||||||
|
|
@ -1003,17 +1003,21 @@ impl MonitorHandle {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
let size = self.size().into();
|
let size = self.size().into();
|
||||||
// FIXME this is not the real refresh rate
|
// FIXME this is not the real refresh rate
|
||||||
// (it is guaranteed to support 32 bit color though)
|
// (it is guaranteed to support 32 bit color though)
|
||||||
std::iter::once(VideoModeHandle {
|
Some(VideoModeHandle {
|
||||||
size,
|
size,
|
||||||
bit_depth: 32,
|
bit_depth: 32,
|
||||||
refresh_rate_millihertz: 60000,
|
refresh_rate_millihertz: 60000,
|
||||||
monitor: self.clone(),
|
monitor: self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||||
|
self.current_video_mode().into_iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,34 @@ impl Clone for NativeDisplayMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VideoModeHandle {
|
impl VideoModeHandle {
|
||||||
|
fn new(monitor: MonitorHandle, mode: NativeDisplayMode, refresh_rate_millihertz: u32) -> Self {
|
||||||
|
unsafe {
|
||||||
|
let pixel_encoding =
|
||||||
|
CFString::wrap_under_create_rule(ffi::CGDisplayModeCopyPixelEncoding(mode.0))
|
||||||
|
.to_string();
|
||||||
|
let bit_depth = if pixel_encoding.eq_ignore_ascii_case(ffi::IO32BitDirectPixels) {
|
||||||
|
32
|
||||||
|
} else if pixel_encoding.eq_ignore_ascii_case(ffi::IO16BitDirectPixels) {
|
||||||
|
16
|
||||||
|
} else if pixel_encoding.eq_ignore_ascii_case(ffi::kIO30BitDirectPixels) {
|
||||||
|
30
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
};
|
||||||
|
|
||||||
|
VideoModeHandle {
|
||||||
|
size: PhysicalSize::new(
|
||||||
|
ffi::CGDisplayModeGetPixelWidth(mode.0) as u32,
|
||||||
|
ffi::CGDisplayModeGetPixelHeight(mode.0) as u32,
|
||||||
|
),
|
||||||
|
refresh_rate_millihertz,
|
||||||
|
bit_depth,
|
||||||
|
monitor: monitor.clone(),
|
||||||
|
native_mode: mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> PhysicalSize<u32> {
|
pub fn size(&self) -> PhysicalSize<u32> {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
@ -212,29 +240,15 @@ impl MonitorHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
|
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
|
||||||
unsafe {
|
let current_display_mode =
|
||||||
let current_display_mode = NativeDisplayMode(CGDisplayCopyDisplayMode(self.0) as _);
|
NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) } as _);
|
||||||
let refresh_rate = ffi::CGDisplayModeGetRefreshRate(current_display_mode.0);
|
refresh_rate_millihertz(self.0, ¤t_display_mode)
|
||||||
if refresh_rate > 0.0 {
|
}
|
||||||
return Some((refresh_rate * 1000.0).round() as u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut display_link = std::ptr::null_mut();
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
if ffi::CVDisplayLinkCreateWithCGDisplay(self.0, &mut display_link)
|
let mode = NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) } as _);
|
||||||
!= ffi::kCVReturnSuccess
|
let refresh_rate_millihertz = refresh_rate_millihertz(self.0, &mode).unwrap_or(0);
|
||||||
{
|
Some(VideoModeHandle::new(self.clone(), mode, refresh_rate_millihertz))
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let time = ffi::CVDisplayLinkGetNominalOutputVideoRefreshPeriod(display_link);
|
|
||||||
ffi::CVDisplayLinkRelease(display_link);
|
|
||||||
|
|
||||||
// This value is indefinite if an invalid display link was specified
|
|
||||||
if time.flags & ffi::kCVTimeIsIndefinite != 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
(time.time_scale as i64).checked_div(time.time_value).map(|v| (v * 1000) as u32)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||||
|
|
@ -268,29 +282,11 @@ impl MonitorHandle {
|
||||||
refresh_rate_millihertz
|
refresh_rate_millihertz
|
||||||
};
|
};
|
||||||
|
|
||||||
let pixel_encoding =
|
VideoModeHandle::new(
|
||||||
CFString::wrap_under_create_rule(ffi::CGDisplayModeCopyPixelEncoding(mode))
|
monitor.clone(),
|
||||||
.to_string();
|
NativeDisplayMode(mode),
|
||||||
let bit_depth = if pixel_encoding.eq_ignore_ascii_case(ffi::IO32BitDirectPixels) {
|
|
||||||
32
|
|
||||||
} else if pixel_encoding.eq_ignore_ascii_case(ffi::IO16BitDirectPixels) {
|
|
||||||
16
|
|
||||||
} else if pixel_encoding.eq_ignore_ascii_case(ffi::kIO30BitDirectPixels) {
|
|
||||||
30
|
|
||||||
} else {
|
|
||||||
unimplemented!()
|
|
||||||
};
|
|
||||||
|
|
||||||
VideoModeHandle {
|
|
||||||
size: PhysicalSize::new(
|
|
||||||
ffi::CGDisplayModeGetPixelWidth(mode) as u32,
|
|
||||||
ffi::CGDisplayModeGetPixelHeight(mode) as u32,
|
|
||||||
),
|
|
||||||
refresh_rate_millihertz,
|
refresh_rate_millihertz,
|
||||||
bit_depth,
|
)
|
||||||
monitor: monitor.clone(),
|
|
||||||
native_mode: NativeDisplayMode(mode),
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -349,3 +345,26 @@ pub(crate) fn flip_window_screen_coordinates(frame: NSRect) -> NSPoint {
|
||||||
let y = main_screen_height - frame.size.height - frame.origin.y;
|
let y = main_screen_height - frame.size.height - frame.origin.y;
|
||||||
NSPoint::new(frame.origin.x, y)
|
NSPoint::new(frame.origin.x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn refresh_rate_millihertz(id: CGDirectDisplayID, mode: &NativeDisplayMode) -> Option<u32> {
|
||||||
|
unsafe {
|
||||||
|
let refresh_rate = ffi::CGDisplayModeGetRefreshRate(mode.0);
|
||||||
|
if refresh_rate > 0.0 {
|
||||||
|
return Some((refresh_rate * 1000.0).round() as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut display_link = std::ptr::null_mut();
|
||||||
|
if ffi::CVDisplayLinkCreateWithCGDisplay(id, &mut display_link) != ffi::kCVReturnSuccess {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let time = ffi::CVDisplayLinkGetNominalOutputVideoRefreshPeriod(display_link);
|
||||||
|
ffi::CVDisplayLinkRelease(display_link);
|
||||||
|
|
||||||
|
// This value is indefinite if an invalid display link was specified
|
||||||
|
if time.flags & ffi::kCVTimeIsIndefinite != 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
(time.time_scale as i64).checked_div(time.time_value).map(|v| (v * 1000) as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,16 @@ impl MonitorHandle {
|
||||||
Some(self.ui_screen.get_on_main(|ui_screen| refresh_rate_millihertz(ui_screen)))
|
Some(self.ui_screen.get_on_main(|ui_screen| refresh_rate_millihertz(ui_screen)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
|
Some(run_on_main(|mtm| {
|
||||||
|
VideoModeHandle::new(
|
||||||
|
self.ui_screen(mtm).clone(),
|
||||||
|
self.ui_screen(mtm).currentMode().unwrap(),
|
||||||
|
mtm,
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||||
run_on_main(|mtm| {
|
run_on_main(|mtm| {
|
||||||
let ui_screen = self.ui_screen(mtm);
|
let ui_screen = self.ui_screen(mtm);
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,11 @@ impl MonitorHandle {
|
||||||
x11_or_wayland!(match self; MonitorHandle(m) => m.scale_factor() as _)
|
x11_or_wayland!(match self; MonitorHandle(m) => m.scale_factor() as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
|
x11_or_wayland!(match self; MonitorHandle(m) => m.current_video_mode())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn video_modes(&self) -> Box<dyn Iterator<Item = VideoModeHandle>> {
|
pub fn video_modes(&self) -> Box<dyn Iterator<Item = VideoModeHandle>> {
|
||||||
x11_or_wayland!(match self; MonitorHandle(m) => Box::new(m.video_modes()))
|
x11_or_wayland!(match self; MonitorHandle(m) => Box::new(m.video_modes()))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use sctk::output::OutputData;
|
use sctk::output::{Mode, OutputData};
|
||||||
use sctk::reexports::client::protocol::wl_output::WlOutput;
|
use sctk::reexports::client::protocol::wl_output::WlOutput;
|
||||||
use sctk::reexports::client::Proxy;
|
use sctk::reexports::client::Proxy;
|
||||||
|
|
||||||
|
|
@ -73,6 +73,18 @@ impl MonitorHandle {
|
||||||
output_data.scale_factor()
|
output_data.scale_factor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn current_video_mode(&self) -> Option<PlatformVideoModeHandle> {
|
||||||
|
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||||
|
output_data.with_output_info(|info| {
|
||||||
|
let mode = info.modes.iter().find(|mode| mode.current).cloned();
|
||||||
|
|
||||||
|
mode.map(|mode| {
|
||||||
|
PlatformVideoModeHandle::Wayland(VideoModeHandle::new(self.clone(), mode))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> {
|
pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> {
|
||||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||||
|
|
@ -81,12 +93,7 @@ impl MonitorHandle {
|
||||||
let monitor = self.clone();
|
let monitor = self.clone();
|
||||||
|
|
||||||
modes.into_iter().map(move |mode| {
|
modes.into_iter().map(move |mode| {
|
||||||
PlatformVideoModeHandle::Wayland(VideoModeHandle {
|
PlatformVideoModeHandle::Wayland(VideoModeHandle::new(monitor.clone(), mode))
|
||||||
size: (mode.dimensions.0 as u32, mode.dimensions.1 as u32).into(),
|
|
||||||
refresh_rate_millihertz: mode.refresh_rate as u32,
|
|
||||||
bit_depth: 32,
|
|
||||||
monitor: monitor.clone(),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,6 +133,15 @@ pub struct VideoModeHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VideoModeHandle {
|
impl VideoModeHandle {
|
||||||
|
fn new(monitor: MonitorHandle, mode: Mode) -> Self {
|
||||||
|
VideoModeHandle {
|
||||||
|
size: (mode.dimensions.0 as u32, mode.dimensions.1 as u32).into(),
|
||||||
|
refresh_rate_millihertz: mode.refresh_rate as u32,
|
||||||
|
bit_depth: 32,
|
||||||
|
monitor: monitor.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn size(&self) -> PhysicalSize<u32> {
|
pub fn size(&self) -> PhysicalSize<u32> {
|
||||||
self.size
|
self.size
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ impl XConnection {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct VideoModeHandle {
|
pub struct VideoModeHandle {
|
||||||
|
pub(crate) current: bool,
|
||||||
pub(crate) size: (u32, u32),
|
pub(crate) size: (u32, u32),
|
||||||
pub(crate) bit_depth: u16,
|
pub(crate) bit_depth: u16,
|
||||||
pub(crate) refresh_rate_millihertz: u32,
|
pub(crate) refresh_rate_millihertz: u32,
|
||||||
|
|
@ -59,8 +60,6 @@ pub struct MonitorHandle {
|
||||||
position: (i32, i32),
|
position: (i32, i32),
|
||||||
/// If the monitor is the primary one
|
/// If the monitor is the primary one
|
||||||
primary: bool,
|
primary: bool,
|
||||||
/// The refresh rate used by monitor.
|
|
||||||
refresh_rate_millihertz: Option<u32>,
|
|
||||||
/// The DPI scale factor
|
/// The DPI scale factor
|
||||||
pub(crate) scale_factor: f64,
|
pub(crate) scale_factor: f64,
|
||||||
/// Used to determine which windows are on this monitor
|
/// Used to determine which windows are on this monitor
|
||||||
|
|
@ -117,20 +116,11 @@ impl MonitorHandle {
|
||||||
let dimensions = (crtc.width as u32, crtc.height as u32);
|
let dimensions = (crtc.width as u32, crtc.height as u32);
|
||||||
let position = (crtc.x as i32, crtc.y as i32);
|
let position = (crtc.x as i32, crtc.y as i32);
|
||||||
|
|
||||||
// Get the refresh rate of the current video mode.
|
|
||||||
let current_mode = crtc.mode;
|
|
||||||
let screen_modes = resources.modes();
|
|
||||||
let refresh_rate_millihertz = screen_modes
|
|
||||||
.iter()
|
|
||||||
.find(|mode| mode.id == current_mode)
|
|
||||||
.and_then(mode_refresh_rate_millihertz);
|
|
||||||
|
|
||||||
let rect = util::AaRect::new(position, dimensions);
|
let rect = util::AaRect::new(position, dimensions);
|
||||||
|
|
||||||
Some(MonitorHandle {
|
Some(MonitorHandle {
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
refresh_rate_millihertz,
|
|
||||||
scale_factor,
|
scale_factor,
|
||||||
dimensions,
|
dimensions,
|
||||||
position,
|
position,
|
||||||
|
|
@ -147,7 +137,6 @@ impl MonitorHandle {
|
||||||
scale_factor: 1.0,
|
scale_factor: 1.0,
|
||||||
dimensions: (1, 1),
|
dimensions: (1, 1),
|
||||||
position: (0, 0),
|
position: (0, 0),
|
||||||
refresh_rate_millihertz: None,
|
|
||||||
primary: true,
|
primary: true,
|
||||||
rect: util::AaRect::new((0, 0), (1, 1)),
|
rect: util::AaRect::new((0, 0), (1, 1)),
|
||||||
video_modes: Vec::new(),
|
video_modes: Vec::new(),
|
||||||
|
|
@ -177,7 +166,9 @@ impl MonitorHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
|
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
|
||||||
self.refresh_rate_millihertz
|
self.video_modes
|
||||||
|
.iter()
|
||||||
|
.find_map(|mode| mode.current.then_some(mode.refresh_rate_millihertz))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -185,6 +176,11 @@ impl MonitorHandle {
|
||||||
self.scale_factor
|
self.scale_factor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn current_video_mode(&self) -> Option<PlatformVideoModeHandle> {
|
||||||
|
self.video_modes.iter().find(|mode| mode.current).cloned().map(PlatformVideoModeHandle::X)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> {
|
pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> {
|
||||||
let monitor = self.clone();
|
let monitor = self.clone();
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ impl XConnection {
|
||||||
let bit_depth = self.default_root().root_depth;
|
let bit_depth = self.default_root().root_depth;
|
||||||
let output_modes = &output_info.modes;
|
let output_modes = &output_info.modes;
|
||||||
let resource_modes = resources.modes();
|
let resource_modes = resources.modes();
|
||||||
|
let current_mode = crtc.mode;
|
||||||
|
|
||||||
let modes = resource_modes
|
let modes = resource_modes
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -82,6 +83,7 @@ impl XConnection {
|
||||||
.filter(|x| output_modes.iter().any(|id| x.id == *id))
|
.filter(|x| output_modes.iter().any(|id| x.id == *id))
|
||||||
.map(|mode| {
|
.map(|mode| {
|
||||||
VideoModeHandle {
|
VideoModeHandle {
|
||||||
|
current: mode.id == current_mode,
|
||||||
size: (mode.width.into(), mode.height.into()),
|
size: (mode.width.into(), mode.height.into()),
|
||||||
refresh_rate_millihertz: monitor::mode_refresh_rate_millihertz(mode)
|
refresh_rate_millihertz: monitor::mode_refresh_rate_millihertz(mode)
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
|
|
|
||||||
|
|
@ -217,17 +217,21 @@ impl MonitorHandle {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
let size = self.size().into();
|
let size = self.size().into();
|
||||||
// FIXME this is not the real refresh rate
|
// FIXME this is not the real refresh rate
|
||||||
// (it is guaranteed to support 32 bit color though)
|
// (it is guaranteed to support 32 bit color though)
|
||||||
std::iter::once(VideoModeHandle {
|
Some(VideoModeHandle {
|
||||||
size,
|
size,
|
||||||
bit_depth: 32,
|
bit_depth: 32,
|
||||||
refresh_rate_millihertz: 60000,
|
refresh_rate_millihertz: 60000,
|
||||||
monitor: self.clone(),
|
monitor: self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||||
|
self.current_video_mode().into_iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ impl MonitorHandle {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
|
Some(VideoModeHandle(self.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn video_modes(&self) -> Once<VideoModeHandle> {
|
pub fn video_modes(&self) -> Once<VideoModeHandle> {
|
||||||
iter::once(VideoModeHandle(self.clone()))
|
iter::once(VideoModeHandle(self.clone()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,20 @@ impl std::fmt::Debug for VideoModeHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VideoModeHandle {
|
impl VideoModeHandle {
|
||||||
|
fn new(monitor: MonitorHandle, mode: DEVMODEW) -> Self {
|
||||||
|
const REQUIRED_FIELDS: u32 =
|
||||||
|
DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
||||||
|
assert!(has_flag(mode.dmFields, REQUIRED_FIELDS));
|
||||||
|
|
||||||
|
VideoModeHandle {
|
||||||
|
size: (mode.dmPelsWidth, mode.dmPelsHeight),
|
||||||
|
bit_depth: mode.dmBitsPerPel as u16,
|
||||||
|
refresh_rate_millihertz: mode.dmDisplayFrequency * 1000,
|
||||||
|
monitor,
|
||||||
|
native_video_mode: Box::new(mode),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> PhysicalSize<u32> {
|
pub fn size(&self) -> PhysicalSize<u32> {
|
||||||
self.size.into()
|
self.size.into()
|
||||||
}
|
}
|
||||||
|
|
@ -207,6 +221,23 @@ impl MonitorHandle {
|
||||||
dpi_to_scale_factor(get_monitor_dpi(self.0).unwrap_or(96))
|
dpi_to_scale_factor(get_monitor_dpi(self.0).unwrap_or(96))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||||
|
let monitor_info = get_monitor_info(self.0).ok()?;
|
||||||
|
let device_name = monitor_info.szDevice.as_ptr();
|
||||||
|
unsafe {
|
||||||
|
let mut mode: DEVMODEW = mem::zeroed();
|
||||||
|
mode.dmSize = mem::size_of_val(&mode) as u16;
|
||||||
|
if EnumDisplaySettingsExW(device_name, ENUM_CURRENT_SETTINGS, &mut mode, 0)
|
||||||
|
== false.into()
|
||||||
|
{
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(VideoModeHandle::new(self.clone(), mode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||||
// EnumDisplaySettingsExW can return duplicate values (or some of the
|
// EnumDisplaySettingsExW can return duplicate values (or some of the
|
||||||
|
|
@ -233,19 +264,9 @@ impl MonitorHandle {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const REQUIRED_FIELDS: u32 =
|
|
||||||
DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
|
||||||
assert!(has_flag(mode.dmFields, REQUIRED_FIELDS));
|
|
||||||
|
|
||||||
// Use Ord impl of RootVideoModeHandle
|
// Use Ord impl of RootVideoModeHandle
|
||||||
modes.insert(RootVideoModeHandle {
|
modes.insert(RootVideoModeHandle {
|
||||||
video_mode: VideoModeHandle {
|
video_mode: VideoModeHandle::new(self.clone(), mode),
|
||||||
size: (mode.dmPelsWidth, mode.dmPelsHeight),
|
|
||||||
bit_depth: mode.dmBitsPerPel as u16,
|
|
||||||
refresh_rate_millihertz: mode.dmDisplayFrequency * 1000,
|
|
||||||
monitor: self.clone(),
|
|
||||||
native_video_mode: Box::new(mode),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue