use objc2::{MainThreadMarker, rc::Retained};
use objc2_app_kit::{NSDeviceResolution, NSScreen};
use objc2_foundation::NSValue;
use winio_primitive::{Monitor, Point, Rect, Size};
use crate::{Error, Result, catch, from_cgsize, transform_cgrect};
pub fn monitor_get_all() -> Result<Vec<Monitor>> {
let mtm = MainThreadMarker::new().ok_or(Error::NotMainThread)?;
let mut res = vec![];
catch(|| {
for screen in NSScreen::screens(mtm) {
let frame = screen.frame();
let vframe = screen.visibleFrame();
let frame_size = from_cgsize(frame.size);
let frame = transform_cgrect(frame_size, frame);
let vframe = transform_cgrect(frame_size, vframe);
let dpi = screen
.deviceDescription()
.objectForKey(unsafe { NSDeviceResolution })
.map(|obj| {
from_cgsize(unsafe { Retained::cast_unchecked::<NSValue>(obj).sizeValue() })
})
.unwrap_or(Size::new(1.0, 1.0));
res.push(Monitor::new(
rect_scale(frame, dpi),
rect_scale(vframe, dpi),
dpi,
))
}
})?;
Ok(res)
}
#[inline]
fn rect_scale(r: Rect, dpi: Size) -> Rect {
Rect::new(
Point::new(r.origin.x * dpi.width, r.origin.y * dpi.height),
Size::new(r.size.width * dpi.width, r.size.height * dpi.height),
)
}