mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-26 22:53:15 -04:00
This should force the use of system libraries for Fontconfig and freetype instead of building them with cmake if missing. This also fixes compilation failures on nightly. Fixes #2373.
90 lines
2.8 KiB
Rust
90 lines
2.8 KiB
Rust
use std::{
|
|
cell::{RefCell, RefMut},
|
|
os::raw::c_void,
|
|
};
|
|
|
|
use cocoa::base::id;
|
|
use objc::{
|
|
declare::ClassDecl,
|
|
runtime::{Class, Object, Sel},
|
|
};
|
|
use once_cell::sync::Lazy;
|
|
|
|
use crate::{platform::macos::ActivationPolicy, platform_impl::platform::app_state::AppState};
|
|
|
|
static AUX_DELEGATE_STATE_NAME: &str = "auxState";
|
|
|
|
pub struct AuxDelegateState {
|
|
pub activation_policy: ActivationPolicy,
|
|
pub default_menu: bool,
|
|
}
|
|
|
|
pub struct AppDelegateClass(pub *const Class);
|
|
unsafe impl Send for AppDelegateClass {}
|
|
unsafe impl Sync for AppDelegateClass {}
|
|
|
|
pub static APP_DELEGATE_CLASS: Lazy<AppDelegateClass> = Lazy::new(|| unsafe {
|
|
let superclass = class!(NSResponder);
|
|
let mut decl = ClassDecl::new("WinitAppDelegate", superclass).unwrap();
|
|
|
|
decl.add_class_method(sel!(new), new as extern "C" fn(&Class, Sel) -> id);
|
|
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
|
|
|
decl.add_method(
|
|
sel!(applicationDidFinishLaunching:),
|
|
did_finish_launching as extern "C" fn(&Object, Sel, id),
|
|
);
|
|
decl.add_method(
|
|
sel!(applicationWillTerminate:),
|
|
will_terminate as extern "C" fn(&Object, Sel, id),
|
|
);
|
|
|
|
decl.add_ivar::<*mut c_void>(AUX_DELEGATE_STATE_NAME);
|
|
|
|
AppDelegateClass(decl.register())
|
|
});
|
|
|
|
/// Safety: Assumes that Object is an instance of APP_DELEGATE_CLASS
|
|
pub unsafe fn get_aux_state_mut(this: &Object) -> RefMut<'_, AuxDelegateState> {
|
|
let ptr: *mut c_void = *this.get_ivar(AUX_DELEGATE_STATE_NAME);
|
|
// Watch out that this needs to be the correct type
|
|
(*(ptr as *mut RefCell<AuxDelegateState>)).borrow_mut()
|
|
}
|
|
|
|
extern "C" fn new(class: &Class, _: Sel) -> id {
|
|
unsafe {
|
|
let this: id = msg_send![class, alloc];
|
|
let this: id = msg_send![this, init];
|
|
// TODO: Remove the need for this initialization here
|
|
(*this).set_ivar(
|
|
AUX_DELEGATE_STATE_NAME,
|
|
Box::into_raw(Box::new(RefCell::new(AuxDelegateState {
|
|
activation_policy: ActivationPolicy::Regular,
|
|
default_menu: true,
|
|
}))) as *mut c_void,
|
|
);
|
|
this
|
|
}
|
|
}
|
|
|
|
extern "C" fn dealloc(this: &Object, _: Sel) {
|
|
unsafe {
|
|
let state_ptr: *mut c_void = *(this.get_ivar(AUX_DELEGATE_STATE_NAME));
|
|
// As soon as the box is constructed it is immediately dropped, releasing the underlying
|
|
// memory
|
|
drop(Box::from_raw(state_ptr as *mut RefCell<AuxDelegateState>));
|
|
}
|
|
}
|
|
|
|
extern "C" fn did_finish_launching(this: &Object, _: Sel, _: id) {
|
|
trace_scope!("applicationDidFinishLaunching:");
|
|
AppState::launched(this);
|
|
}
|
|
|
|
extern "C" fn will_terminate(_this: &Object, _: Sel, _: id) {
|
|
trace!("Triggered `applicationWillTerminate`");
|
|
// TODO: Notify every window that it will be destroyed, like done in iOS?
|
|
AppState::exit();
|
|
trace!("Completed `applicationWillTerminate`");
|
|
}
|