use {
libc::c_void,
objc::{
declare::ClassDecl,
runtime::{Class, Object, Sel},
sel, sel_impl, Message,
},
objc_foundation::{INSObject, NSObject},
objc_id::Id,
std::mem,
};
pub(crate) enum Callback {}
unsafe impl Message for Callback {}
pub(crate) struct CallbackState {
cb: Box<dyn Fn() -> ()>,
}
impl Callback {
pub(crate) fn from(cb: Box<dyn Fn() -> ()>) -> Id<Self> {
let cbs = CallbackState { cb };
let bcbs = Box::new(cbs);
let ptr = Box::into_raw(bcbs);
let ptr = ptr as *mut c_void as usize;
let mut oid = <Callback as INSObject>::new();
(*oid).setptr(ptr);
oid
}
pub(crate) fn setptr(&mut self, uptr: usize) {
unsafe {
let obj = &mut *(self as *mut _ as *mut ::objc::runtime::Object);
obj.set_ivar("_cbptr", uptr);
}
}
}
impl INSObject for Callback {
fn class() -> &'static Class {
let cname = "Callback";
let mut klass = Class::get(cname);
if klass.is_none() {
let superclass = NSObject::class();
let mut decl = ClassDecl::new(&cname, superclass).unwrap();
decl.add_ivar::<usize>("_cbptr");
extern "C" fn sysbar_callback_call(this: &Object, _cmd: Sel) {
unsafe {
let pval: usize = *this.get_ivar("_cbptr");
let ptr = pval as *mut c_void;
let ptr = ptr as *mut CallbackState;
let bcbs: Box<CallbackState> = Box::from_raw(ptr);
{
(*bcbs.cb)();
}
mem::forget(bcbs);
}
}
unsafe {
decl.add_method(
sel!(call),
sysbar_callback_call as extern "C" fn(&Object, Sel),
);
}
decl.register();
klass = Class::get(cname);
}
klass.unwrap()
}
}