Require setting the activation policy on the event loop (#1922)
* Require setting the activation policy on the event loop * Run cargo fmt * Update changelog * Fixes and tweaks from review * Correct comment in app_state.rs Co-authored-by: Mads Marquart <mads@marquart.dk>
This commit is contained in:
parent
0986fae066
commit
cdeb1c3828
9 changed files with 110 additions and 56 deletions
|
|
@ -1,9 +1,23 @@
|
|||
use super::app_state::AppState;
|
||||
use crate::{platform::macos::ActivationPolicy, platform_impl::platform::app_state::AppState};
|
||||
|
||||
use cocoa::base::id;
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
runtime::{Class, Object, Sel},
|
||||
};
|
||||
use std::{
|
||||
cell::{RefCell, RefMut},
|
||||
os::raw::c_void,
|
||||
};
|
||||
|
||||
static AUX_DELEGATE_STATE_NAME: &str = "auxState";
|
||||
|
||||
pub struct AuxDelegateState {
|
||||
/// We store this value in order to be able to defer setting the activation policy until
|
||||
/// after the app has finished launching. If the activation policy is set earlier, the
|
||||
/// menubar is initially unresponsive on macOS 10.15 for example.
|
||||
pub activation_policy: ActivationPolicy,
|
||||
}
|
||||
|
||||
pub struct AppDelegateClass(pub *const Class);
|
||||
unsafe impl Send for AppDelegateClass {}
|
||||
|
|
@ -14,17 +28,51 @@ lazy_static! {
|
|||
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_ivar::<*mut c_void>(AUX_DELEGATE_STATE_NAME);
|
||||
|
||||
AppDelegateClass(decl.register())
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" fn did_finish_launching(_: &Object, _: Sel, _: id) {
|
||||
/// 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];
|
||||
(*this).set_ivar(
|
||||
AUX_DELEGATE_STATE_NAME,
|
||||
Box::into_raw(Box::new(RefCell::new(AuxDelegateState {
|
||||
activation_policy: ActivationPolicy::Regular,
|
||||
}))) 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
|
||||
Box::from_raw(state_ptr as *mut RefCell<AuxDelegateState>);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn did_finish_launching(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `applicationDidFinishLaunching`");
|
||||
AppState::launched();
|
||||
AppState::launched(this);
|
||||
trace!("Completed `applicationDidFinishLaunching`");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue