Support listing available video modes for a monitor (#896)

* Support listing available video modes for a monitor

* Use derivative for Windows `MonitorHandle`

* Update FEATURES.md

* Fix multiline if statement

* Add documentation for `VideoMode` type
This commit is contained in:
Aleksi Juvani 2019-06-12 21:07:25 +03:00 committed by Osspial
parent 2b89ddec15
commit 47b5dfa034
13 changed files with 254 additions and 23 deletions

View file

@ -1,9 +1,18 @@
use std::{collections::VecDeque, fmt};
use cocoa::{appkit::NSScreen, base::{id, nil}, foundation::{NSString, NSUInteger}};
use core_graphics::display::{CGDirectDisplayID, CGDisplay, CGDisplayBounds};
use cocoa::{
appkit::NSScreen,
base::{id, nil},
foundation::{NSString, NSUInteger},
};
use core_graphics::display::{CGDirectDisplayID, CGDisplay, CGDisplayBounds, CGDisplayMode};
use core_video_sys::{
kCVReturnSuccess, kCVTimeIsIndefinite, CVDisplayLinkCreateWithCGDisplay,
CVDisplayLinkGetNominalOutputVideoRefreshPeriod, CVDisplayLinkRelease,
};
use dpi::{PhysicalPosition, PhysicalSize};
use monitor::VideoMode;
use platform_impl::platform::util::IdRef;
#[derive(Clone, PartialEq)]
@ -93,6 +102,44 @@ impl MonitorHandle {
unsafe { NSScreen::backingScaleFactor(screen) as f64 }
}
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
let cv_refresh_rate = unsafe {
let mut display_link = std::ptr::null_mut();
assert_eq!(
CVDisplayLinkCreateWithCGDisplay(self.0, &mut display_link),
kCVReturnSuccess
);
let time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(display_link);
CVDisplayLinkRelease(display_link);
// This value is indefinite if an invalid display link was specified
assert!(time.flags & kCVTimeIsIndefinite == 0);
time.timeScale as i64 / time.timeValue
};
CGDisplayMode::all_display_modes(self.0, std::ptr::null())
.expect("failed to obtain list of display modes")
.into_iter()
.map(move |mode| {
let cg_refresh_rate = mode.refresh_rate().round() as i64;
// CGDisplayModeGetRefreshRate returns 0.0 for any display that
// isn't a CRT
let refresh_rate = if cg_refresh_rate > 0 {
cg_refresh_rate
} else {
cv_refresh_rate
};
VideoMode {
dimensions: (mode.width() as u32, mode.height() as u32),
refresh_rate: refresh_rate as u16,
bit_depth: mode.bit_depth() as u16,
}
})
}
pub(crate) fn ns_screen(&self) -> Option<id> {
unsafe {
let native_id = self.native_identifier();