apple: Implement wake-ups using system mechanisms (#4146)
Do the wake-up inside the perform callback on `CFRunLoopSource`.
This commit is contained in:
parent
aa8ebdc795
commit
39c0862198
7 changed files with 154 additions and 148 deletions
|
|
@ -1,7 +1,6 @@
|
|||
use std::cell::{Cell, OnceCell, RefCell};
|
||||
use std::mem;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::atomic::Ordering as AtomicOrdering;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
|
|
@ -11,7 +10,8 @@ use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSRunningAppli
|
|||
use objc2_foundation::NSNotification;
|
||||
|
||||
use super::super::event_handler::EventHandler;
|
||||
use super::event_loop::{stop_app_immediately, ActiveEventLoop, EventLoopProxy, PanicInfo};
|
||||
use super::super::event_loop_proxy::EventLoopProxy;
|
||||
use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo};
|
||||
use super::menu;
|
||||
use super::observer::{EventLoopWaker, RunLoop};
|
||||
use crate::application::ApplicationHandler;
|
||||
|
|
@ -59,13 +59,17 @@ impl AppState {
|
|||
default_menu: bool,
|
||||
activate_ignoring_other_apps: bool,
|
||||
) -> Rc<Self> {
|
||||
let this = Rc::new(AppState {
|
||||
let event_loop_proxy = Arc::new(EventLoopProxy::new(mtm, move || {
|
||||
Self::get(mtm).with_handler(|app, event_loop| app.proxy_wake_up(event_loop));
|
||||
}));
|
||||
|
||||
let this = Rc::new(Self {
|
||||
mtm,
|
||||
activation_policy,
|
||||
event_loop_proxy: Arc::new(EventLoopProxy::new()),
|
||||
default_menu,
|
||||
activate_ignoring_other_apps,
|
||||
run_loop: RunLoop::main(mtm),
|
||||
event_loop_proxy,
|
||||
event_handler: EventHandler::new(),
|
||||
stop_on_launch: Cell::new(false),
|
||||
stop_before_wait: Cell::new(false),
|
||||
|
|
@ -351,10 +355,6 @@ impl AppState {
|
|||
return;
|
||||
}
|
||||
|
||||
if self.event_loop_proxy.wake_up.swap(false, AtomicOrdering::Relaxed) {
|
||||
self.with_handler(|app, event_loop| app.proxy_wake_up(event_loop));
|
||||
}
|
||||
|
||||
let redraw = mem::take(&mut *self.pending_redraw.borrow_mut());
|
||||
for window_id in redraw {
|
||||
self.with_handler(|app, event_loop| {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
use std::any::Any;
|
||||
use std::cell::Cell;
|
||||
use std::os::raw::c_void;
|
||||
use std::panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe};
|
||||
use std::ptr;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
|
@ -15,11 +12,6 @@ use objc2_app_kit::{
|
|||
NSApplication, NSApplicationActivationPolicy, NSApplicationDidFinishLaunchingNotification,
|
||||
NSApplicationWillTerminateNotification, NSWindow,
|
||||
};
|
||||
use objc2_core_foundation::{
|
||||
kCFRunLoopCommonModes, CFIndex, CFRetained, CFRunLoopAddSource, CFRunLoopGetMain,
|
||||
CFRunLoopSource, CFRunLoopSourceContext, CFRunLoopSourceCreate, CFRunLoopSourceSignal,
|
||||
CFRunLoopWakeUp,
|
||||
};
|
||||
use objc2_foundation::{NSNotificationCenter, NSObjectProtocol};
|
||||
use rwh_06::HasDisplayHandle;
|
||||
|
||||
|
|
@ -34,8 +26,7 @@ use crate::application::ApplicationHandler;
|
|||
use crate::error::{EventLoopError, RequestError};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
|
||||
OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
EventLoopProxy as CoreEventLoopProxy, OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::platform::macos::ActivationPolicy;
|
||||
|
|
@ -429,54 +420,3 @@ pub fn stop_app_on_panic<F: FnOnce() -> R + UnwindSafe, R>(
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EventLoopProxy {
|
||||
pub(crate) wake_up: AtomicBool,
|
||||
source: CFRetained<CFRunLoopSource>,
|
||||
}
|
||||
|
||||
unsafe impl Send for EventLoopProxy {}
|
||||
unsafe impl Sync for EventLoopProxy {}
|
||||
|
||||
impl EventLoopProxy {
|
||||
pub(crate) fn new() -> Self {
|
||||
unsafe {
|
||||
// just wake up the eventloop
|
||||
extern "C-unwind" fn event_loop_proxy_handler(_context: *mut c_void) {}
|
||||
|
||||
// adding a Source to the main CFRunLoop lets us wake it up and
|
||||
// process user events through the normal OS EventLoop mechanisms.
|
||||
let rl = CFRunLoopGetMain().unwrap();
|
||||
let mut context = CFRunLoopSourceContext {
|
||||
version: 0,
|
||||
info: ptr::null_mut(),
|
||||
retain: None,
|
||||
release: None,
|
||||
copyDescription: None,
|
||||
equal: None,
|
||||
hash: None,
|
||||
schedule: None,
|
||||
cancel: None,
|
||||
perform: Some(event_loop_proxy_handler),
|
||||
};
|
||||
let source = CFRunLoopSourceCreate(None, CFIndex::MAX - 1, &mut context).unwrap();
|
||||
CFRunLoopAddSource(&rl, Some(&source), kCFRunLoopCommonModes);
|
||||
CFRunLoopWakeUp(&rl);
|
||||
|
||||
EventLoopProxy { wake_up: AtomicBool::new(false), source }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventLoopProxyProvider for EventLoopProxy {
|
||||
fn wake_up(&self) {
|
||||
self.wake_up.store(true, AtomicOrdering::Relaxed);
|
||||
unsafe {
|
||||
// Let the main thread know there's a new event.
|
||||
CFRunLoopSourceSignal(&self.source);
|
||||
let rl = CFRunLoopGetMain().unwrap();
|
||||
CFRunLoopWakeUp(&rl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue