winio-ui-app-kit 0.6.0

AppKit backend for winio.
Documentation
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),
    )
}