use std::{ffi::CString, mem::transmute, ptr::null_mut};
use spyne_ffi::c::macos::{general::{constants::RTLD_NOW, functions::dlopen}, graphics::{appkit::{NS_BACKING_STORE_BUFFERED, NS_WINDOW_STYLE_MASK_CLOSABLE, NS_WINDOW_STYLE_MASK_MINIATURIZABLE, NS_WINDOW_STYLE_MASK_RESIZABLE, NS_WINDOW_STYLE_MASK_TITLED, NSBackingStoreType, NSPoint, NSRect, NSSize, NSWindowStyleMask}, objc_runtime::{Id, ObjCFunctions, Sel}}};
pub struct AppKitWindow {
pub functions: ObjCFunctions,
pub caml: Id,
pub nsapp: Id,
pub nswindow: Id
}
impl AppKitWindow {
pub fn create_window(origin: (f64, f64), dimensions: (f64, f64)) -> AppKitWindow {
let functions = unsafe { ObjCFunctions::load() };
let appkit_lib_name = CString::new("/System/Library/Frameworks/AppKit.framework/AppKit").unwrap();
unsafe { dlopen(appkit_lib_name.as_ptr(), RTLD_NOW) };
let quartz_core_name = CString::new("/System/Library/Frameworks/QuartzCore.framework/QuartzCore").unwrap();
unsafe { dlopen(quartz_core_name.as_ptr(), RTLD_NOW) };
let nsapp_class = unsafe { (functions.objc_get_class)(CString::new("NSApplication").unwrap().as_ptr()) };
let nsapp_sel = unsafe { (functions.sel_register_name)(CString::new("sharedApplication").unwrap().as_ptr()) };
let nsapp_msg_send: unsafe extern "C" fn(Id, Sel) -> Id = unsafe { transmute(functions.objc_msg_send) };
let nsapp_ptr = unsafe { nsapp_msg_send(nsapp_class, nsapp_sel) };
if nsapp_ptr.is_null() {
panic!("Got a null ptr on nsapp");
}
let sap_sel = unsafe { (functions.sel_register_name)(CString::new("setActivationPolicy:").unwrap().as_ptr()) };
let sap_msg_send: unsafe extern "C" fn(Id, Sel, i64) = unsafe { transmute(functions.objc_msg_send) };
unsafe { sap_msg_send(nsapp_ptr, sap_sel, 0) };
let nswindow_class = unsafe { (functions.objc_get_class)(CString::new("NSWindow").unwrap().as_ptr()) };
let nswindow_sel = unsafe { (functions.sel_register_name)(CString::new("alloc").unwrap().as_ptr()) };
let nswindow_msg_send: unsafe extern "C" fn(Id, Sel) -> Id = unsafe { transmute(functions.objc_msg_send) };
let nswindow_ptr = unsafe { nswindow_msg_send(nswindow_class, nswindow_sel) };
if nswindow_ptr.is_null() {
panic!("Got a null ptr on nswindow");
}
let iwcr_sel = unsafe { (functions.sel_register_name)(CString::new("initWithContentRect:styleMask:backing:defer:").unwrap().as_ptr()) };
let iwcr_msg_send: unsafe extern "C" fn(Id, Sel, NSRect, NSWindowStyleMask, NSBackingStoreType, bool) -> Id = unsafe { transmute(functions.objc_msg_send) };
let ns_rect = NSRect {
origin: NSPoint {
x: origin.0,
y: origin.1,
},
size: NSSize {
width: dimensions.0,
height: dimensions.1,
}
};
let style_mask: NSWindowStyleMask = NS_WINDOW_STYLE_MASK_TITLED | NS_WINDOW_STYLE_MASK_CLOSABLE | NS_WINDOW_STYLE_MASK_MINIATURIZABLE | NS_WINDOW_STYLE_MASK_RESIZABLE;
let iwcr_ptr = unsafe { iwcr_msg_send(nswindow_ptr, iwcr_sel, ns_rect, style_mask, NS_BACKING_STORE_BUFFERED, false) };
if iwcr_ptr.is_null() {
panic!("Got a null ptr on iwcr");
}
let cv_sel = unsafe { (functions.sel_register_name)(CString::new("contentView").unwrap().as_ptr()) };
let cv_msg_send: unsafe extern "C" fn(Id, Sel) -> Id = unsafe { transmute(functions.objc_msg_send) };
let cv_ptr = unsafe { cv_msg_send(nswindow_ptr, cv_sel) };
if cv_ptr.is_null() {
panic!("Got a null ptr on cv");
}
let swl_sel = unsafe { (functions.sel_register_name)(CString::new("setWantsLayer:").unwrap().as_ptr()) };
let swl_msg_send: unsafe extern "C" fn(Id, Sel, bool) = unsafe { transmute(functions.objc_msg_send) };
unsafe { swl_msg_send(cv_ptr, swl_sel, true) };
let caml_class = unsafe { (functions.objc_get_class)(CString::new("CAMetalLayer").unwrap().as_ptr()) };
let caml_sel = unsafe { (functions.sel_register_name)(CString::new("layer").unwrap().as_ptr()) };
let caml_msg_send: unsafe extern "C" fn(Id, Sel) -> Id = unsafe { transmute(functions.objc_msg_send) };
let caml_ptr = unsafe { caml_msg_send(caml_class, caml_sel) };
if caml_ptr.is_null() {
panic!("Got a null ptr on caml");
}
let sl_sel = unsafe { (functions.sel_register_name)(CString::new("setLayer:").unwrap().as_ptr()) };
let sl_msg_send: unsafe extern "C" fn(Id, Sel, Id) = unsafe { transmute(functions.objc_msg_send) };
unsafe { sl_msg_send(cv_ptr, sl_sel, caml_ptr) };
let mkaof_sel = unsafe { (functions.sel_register_name)(CString::new("makeKeyAndOrderFront:").unwrap().as_ptr()) };
let mkaof_msg_send: unsafe extern "C" fn(Id, Sel, Id) = unsafe { transmute(functions.objc_msg_send) };
unsafe { mkaof_msg_send(nswindow_ptr, mkaof_sel, null_mut()) };
let aioa_sel = unsafe { (functions.sel_register_name)(CString::new("activateIgnoringOtherApps:").unwrap().as_ptr()) };
let aioa_msg_send: unsafe extern "C" fn(Id, Sel, bool) = unsafe { transmute(functions.objc_msg_send) };
unsafe { aioa_msg_send(nsapp_ptr, aioa_sel, true) };
AppKitWindow { functions, caml: caml_ptr, nsapp: nsapp_ptr, nswindow: nswindow_ptr }
}
}