#![cfg(target_os = "macos")]
#![allow(unsafe_code)]
use core::ffi::c_void;
use cocoa::appkit::{NSApplication, NSEventMask, NSView};
use cocoa::base::{BOOL, NO, YES, id, nil};
use cocoa::foundation::{NSDefaultRunLoopMode, NSPoint, NSRect, NSSize};
use mkapk_host::ParentWindowHandle;
use mkgraphic::prelude::{App, Extent, Window};
use objc::runtime::Class;
pub struct MainWindow {
#[allow(dead_code)]
app: Option<App>,
#[allow(dead_code)]
window: Window,
ns_window: id,
}
impl MainWindow {
pub fn create(title: &str, width: u32, height: u32) -> (Self, ParentWindowHandle) {
let app = App::new();
let mut window = Window::new(title, Extent::new(width as f32, height as f32));
let raw_window = window
.handle()
.expect("mkgraphic window should expose a native NSWindow handle on macOS");
let ns_window = raw_window as id;
let frame = NSRect::new(
NSPoint::new(0.0, 0.0),
NSSize::new(width as f64, height as f64),
);
let content_view: id = unsafe {
let view = NSView::alloc(nil).initWithFrame_(frame);
let _: () = msg_send![ns_window, setContentView: view];
let _: () = msg_send![view, release];
view
};
window.show();
(
Self {
app: Some(app),
window,
ns_window,
},
ParentWindowHandle::Mac(content_view as *mut c_void),
)
}
pub fn pump_events(&self) -> bool {
unsafe {
let pool: id = msg_send![
Class::get("NSAutoreleasePool").expect("NSAutoreleasePool"),
new
];
let distant_past: id = msg_send![Class::get("NSDate").expect("NSDate"), distantPast];
let app = cocoa::appkit::NSApp();
loop {
let event = app.nextEventMatchingMask_untilDate_inMode_dequeue_(
NSEventMask::NSAnyEventMask.bits(),
distant_past,
NSDefaultRunLoopMode,
YES,
);
if event == nil {
break;
}
app.sendEvent_(event);
}
let visible: BOOL = msg_send![self.ns_window, isVisible];
let _: () = msg_send![pool, release];
visible != NO
}
}
pub fn destroy(self) {
unsafe {
let _: () = msg_send![self.ns_window, close];
}
}
}