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