1 use std::{
2     collections::VecDeque, marker::PhantomData, mem, os::raw::c_void, process, ptr, rc::Rc,
3     sync::mpsc,
4 };
5 
6 use cocoa::{
7     appkit::NSApp,
8     base::{id, nil},
9     foundation::NSAutoreleasePool,
10 };
11 
12 use crate::{
13     event::Event,
14     event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget},
15     monitor::MonitorHandle as RootMonitorHandle,
16     platform_impl::platform::{
17         app::APP_CLASS,
18         app_delegate::APP_DELEGATE_CLASS,
19         app_state::AppState,
20         monitor::{self, MonitorHandle},
21         observer::*,
22         util::IdRef,
23     },
24 };
25 
26 pub struct EventLoopWindowTarget<T: 'static> {
27     pub sender: mpsc::Sender<T>, // this is only here to be cloned elsewhere
28     pub receiver: mpsc::Receiver<T>,
29 }
30 
31 impl<T> Default for EventLoopWindowTarget<T> {
default() -> Self32     fn default() -> Self {
33         let (sender, receiver) = mpsc::channel();
34         EventLoopWindowTarget { sender, receiver }
35     }
36 }
37 
38 impl<T: 'static> EventLoopWindowTarget<T> {
39     #[inline]
available_monitors(&self) -> VecDeque<MonitorHandle>40     pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
41         monitor::available_monitors()
42     }
43 
44     #[inline]
primary_monitor(&self) -> Option<RootMonitorHandle>45     pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
46         let monitor = monitor::primary_monitor();
47         Some(RootMonitorHandle { inner: monitor })
48     }
49 }
50 
51 pub struct EventLoop<T: 'static> {
52     window_target: Rc<RootWindowTarget<T>>,
53     _delegate: IdRef,
54 }
55 
56 impl<T> EventLoop<T> {
new() -> Self57     pub fn new() -> Self {
58         let delegate = unsafe {
59             if !msg_send![class!(NSThread), isMainThread] {
60                 panic!("On macOS, `EventLoop` must be created on the main thread!");
61             }
62 
63             // This must be done before `NSApp()` (equivalent to sending
64             // `sharedApplication`) is called anywhere else, or we'll end up
65             // with the wrong `NSApplication` class and the wrong thread could
66             // be marked as main.
67             let app: id = msg_send![APP_CLASS.0, sharedApplication];
68 
69             let delegate = IdRef::new(msg_send![APP_DELEGATE_CLASS.0, new]);
70             let pool = NSAutoreleasePool::new(nil);
71             let _: () = msg_send![app, setDelegate:*delegate];
72             let _: () = msg_send![pool, drain];
73             delegate
74         };
75         setup_control_flow_observers();
76         EventLoop {
77             window_target: Rc::new(RootWindowTarget {
78                 p: Default::default(),
79                 _marker: PhantomData,
80             }),
81             _delegate: delegate,
82         }
83     }
84 
window_target(&self) -> &RootWindowTarget<T>85     pub fn window_target(&self) -> &RootWindowTarget<T> {
86         &self.window_target
87     }
88 
run<F>(mut self, callback: F) -> ! where F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),89     pub fn run<F>(mut self, callback: F) -> !
90     where
91         F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
92     {
93         self.run_return(callback);
94         process::exit(0);
95     }
96 
run_return<F>(&mut self, callback: F) where F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),97     pub fn run_return<F>(&mut self, callback: F)
98     where
99         F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
100     {
101         unsafe {
102             let pool = NSAutoreleasePool::new(nil);
103             let app = NSApp();
104             assert_ne!(app, nil);
105             AppState::set_callback(callback, Rc::clone(&self.window_target));
106             let _: () = msg_send![app, run];
107             AppState::exit();
108             pool.drain();
109         }
110     }
111 
create_proxy(&self) -> Proxy<T>112     pub fn create_proxy(&self) -> Proxy<T> {
113         Proxy::new(self.window_target.p.sender.clone())
114     }
115 }
116 
117 pub struct Proxy<T> {
118     sender: mpsc::Sender<T>,
119     source: CFRunLoopSourceRef,
120 }
121 
122 unsafe impl<T: Send> Send for Proxy<T> {}
123 
124 impl<T> Drop for Proxy<T> {
drop(&mut self)125     fn drop(&mut self) {
126         unsafe {
127             CFRelease(self.source as _);
128         }
129     }
130 }
131 
132 impl<T> Clone for Proxy<T> {
clone(&self) -> Self133     fn clone(&self) -> Self {
134         Proxy::new(self.sender.clone())
135     }
136 }
137 
138 impl<T> Proxy<T> {
new(sender: mpsc::Sender<T>) -> Self139     fn new(sender: mpsc::Sender<T>) -> Self {
140         unsafe {
141             // just wake up the eventloop
142             extern "C" fn event_loop_proxy_handler(_: *mut c_void) {}
143 
144             // adding a Source to the main CFRunLoop lets us wake it up and
145             // process user events through the normal OS EventLoop mechanisms.
146             let rl = CFRunLoopGetMain();
147             let mut context: CFRunLoopSourceContext = mem::zeroed();
148             context.perform = Some(event_loop_proxy_handler);
149             let source =
150                 CFRunLoopSourceCreate(ptr::null_mut(), CFIndex::max_value() - 1, &mut context);
151             CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes);
152             CFRunLoopWakeUp(rl);
153 
154             Proxy { sender, source }
155         }
156     }
157 
send_event(&self, event: T) -> Result<(), EventLoopClosed<T>>158     pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
159         self.sender
160             .send(event)
161             .map_err(|mpsc::SendError(x)| EventLoopClosed(x))?;
162         unsafe {
163             // let the main thread know there's a new event
164             CFRunLoopSourceSignal(self.source);
165             let rl = CFRunLoopGetMain();
166             CFRunLoopWakeUp(rl);
167         }
168         Ok(())
169     }
170 }
171