use crate::error::{VZError, VZResult};
use crate::ffi::{get_class, nsarray, release};
use crate::{msg_send, msg_send_void};
use objc2::runtime::AnyObject;
use std::ffi::c_void;
pub struct MacGraphicsDeviceConfiguration {
inner: *mut AnyObject,
}
unsafe impl Send for MacGraphicsDeviceConfiguration {}
impl MacGraphicsDeviceConfiguration {
pub fn new(
width_in_pixels: isize,
height_in_pixels: isize,
pixels_per_inch: isize,
) -> VZResult<Self> {
unsafe {
let display_cls = get_class("VZMacGraphicsDisplayConfiguration").ok_or_else(|| {
VZError::Internal {
code: -1,
message: "VZMacGraphicsDisplayConfiguration class not found".into(),
}
})?;
let display_alloc = msg_send!(display_cls, alloc);
let init_sel = objc2::sel!(initWithWidthInPixels:heightInPixels:pixelsPerInch:);
let init_fn: unsafe extern "C" fn(
*mut AnyObject,
objc2::runtime::Sel,
isize,
isize,
isize,
) -> *mut AnyObject =
std::mem::transmute(crate::ffi::runtime::objc_msgSend as *const c_void);
let display = init_fn(
display_alloc,
init_sel,
width_in_pixels,
height_in_pixels,
pixels_per_inch,
);
if display.is_null() {
return Err(VZError::InvalidConfiguration(
"failed to create macOS graphics display".into(),
));
}
let device_cls = match get_class("VZMacGraphicsDeviceConfiguration") {
Some(cls) => cls,
None => {
release(display);
return Err(VZError::Internal {
code: -1,
message: "VZMacGraphicsDeviceConfiguration class not found".into(),
});
}
};
let device = msg_send!(msg_send!(device_cls, alloc), init);
if device.is_null() {
release(display);
return Err(VZError::Internal {
code: -1,
message: "Failed to create macOS graphics device".into(),
});
}
let displays = nsarray(&[display]);
msg_send_void!(device, setDisplays: displays);
release(display);
Ok(Self { inner: device })
}
}
#[must_use]
pub fn into_ptr(self) -> *mut AnyObject {
let ptr = self.inner;
std::mem::forget(self);
ptr
}
}
impl Drop for MacGraphicsDeviceConfiguration {
fn drop(&mut self) {
if !self.inner.is_null() {
release(self.inner);
}
}
}