Extract a platform::Lifecycle trait

This will allow us to make platform::Platform be Send + Sync and keep the lifecycle on the main thread.
This commit is contained in:
Nathan Sobo 2021-06-07 17:02:24 -06:00
parent 748c101076
commit 14b519f78d
5 changed files with 161 additions and 129 deletions

View file

@ -112,10 +112,12 @@ impl App {
asset_source: A, asset_source: A,
f: F, f: F,
) -> T { ) -> T {
let lifecycle = platform::test::lifecycle();
let platform = platform::test::platform(); let platform = platform::test::platform();
let foreground = Rc::new(executor::Foreground::test()); let foreground = Rc::new(executor::Foreground::test());
let cx = Rc::new(RefCell::new(MutableAppContext::new( let cx = Rc::new(RefCell::new(MutableAppContext::new(
foreground, foreground,
Rc::new(lifecycle),
Rc::new(platform), Rc::new(platform),
asset_source, asset_source,
))); )));
@ -129,11 +131,13 @@ impl App {
Fn: FnOnce(TestAppContext) -> F, Fn: FnOnce(TestAppContext) -> F,
F: Future<Output = T>, F: Future<Output = T>,
{ {
let lifecycle = Rc::new(platform::test::lifecycle());
let platform = Rc::new(platform::test::platform()); let platform = Rc::new(platform::test::platform());
let foreground = Rc::new(executor::Foreground::test()); let foreground = Rc::new(executor::Foreground::test());
let cx = TestAppContext( let cx = TestAppContext(
Rc::new(RefCell::new(MutableAppContext::new( Rc::new(RefCell::new(MutableAppContext::new(
foreground.clone(), foreground.clone(),
lifecycle,
platform.clone(), platform.clone(),
asset_source, asset_source,
))), ))),
@ -146,16 +150,18 @@ impl App {
} }
pub fn new(asset_source: impl AssetSource) -> Result<Self> { pub fn new(asset_source: impl AssetSource) -> Result<Self> {
let lifecycle = platform::current::lifecycle();
let platform = platform::current::platform(); let platform = platform::current::platform();
let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?); let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
let app = Self(Rc::new(RefCell::new(MutableAppContext::new( let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
foreground, foreground,
lifecycle.clone(),
platform.clone(), platform.clone(),
asset_source, asset_source,
)))); ))));
let cx = app.0.clone(); let cx = app.0.clone();
platform.on_menu_command(Box::new(move |command, arg| { lifecycle.on_menu_command(Box::new(move |command, arg| {
let mut cx = cx.borrow_mut(); let mut cx = cx.borrow_mut();
if let Some(key_window_id) = cx.platform.key_window_id() { if let Some(key_window_id) = cx.platform.key_window_id() {
if let Some((presenter, _)) = cx.presenters_and_platform_windows.get(&key_window_id) if let Some((presenter, _)) = cx.presenters_and_platform_windows.get(&key_window_id)
@ -181,8 +187,8 @@ impl App {
{ {
let cx = self.0.clone(); let cx = self.0.clone();
self.0 self.0
.borrow() .borrow_mut()
.platform .lifecycle
.on_become_active(Box::new(move || callback(&mut *cx.borrow_mut()))); .on_become_active(Box::new(move || callback(&mut *cx.borrow_mut())));
self self
} }
@ -193,8 +199,8 @@ impl App {
{ {
let cx = self.0.clone(); let cx = self.0.clone();
self.0 self.0
.borrow() .borrow_mut()
.platform .lifecycle
.on_resign_active(Box::new(move || callback(&mut *cx.borrow_mut()))); .on_resign_active(Box::new(move || callback(&mut *cx.borrow_mut())));
self self
} }
@ -204,9 +210,12 @@ impl App {
F: 'static + FnMut(Event, &mut MutableAppContext) -> bool, F: 'static + FnMut(Event, &mut MutableAppContext) -> bool,
{ {
let cx = self.0.clone(); let cx = self.0.clone();
self.0.borrow().platform.on_event(Box::new(move |event| { self.0
callback(event, &mut *cx.borrow_mut()) .borrow_mut()
})); .lifecycle
.on_event(Box::new(move |event| {
callback(event, &mut *cx.borrow_mut())
}));
self self
} }
@ -216,8 +225,8 @@ impl App {
{ {
let cx = self.0.clone(); let cx = self.0.clone();
self.0 self.0
.borrow() .borrow_mut()
.platform .lifecycle
.on_open_files(Box::new(move |paths| { .on_open_files(Box::new(move |paths| {
callback(paths, &mut *cx.borrow_mut()) callback(paths, &mut *cx.borrow_mut())
})); }));
@ -228,8 +237,8 @@ impl App {
where where
F: 'static + FnOnce(&mut MutableAppContext), F: 'static + FnOnce(&mut MutableAppContext),
{ {
let platform = self.0.borrow().platform.clone(); let lifecycle = self.0.borrow().lifecycle.clone();
platform.run(Box::new(move || { lifecycle.run(Box::new(move || {
let mut cx = self.0.borrow_mut(); let mut cx = self.0.borrow_mut();
on_finish_launching(&mut *cx); on_finish_launching(&mut *cx);
})) }))
@ -516,6 +525,7 @@ type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext);
pub struct MutableAppContext { pub struct MutableAppContext {
weak_self: Option<rc::Weak<RefCell<Self>>>, weak_self: Option<rc::Weak<RefCell<Self>>>,
lifecycle: Rc<dyn platform::Lifecycle>,
platform: Rc<dyn platform::Platform>, platform: Rc<dyn platform::Platform>,
assets: Arc<AssetCache>, assets: Arc<AssetCache>,
cx: AppContext, cx: AppContext,
@ -537,14 +547,16 @@ pub struct MutableAppContext {
} }
impl MutableAppContext { impl MutableAppContext {
pub fn new( fn new(
foreground: Rc<executor::Foreground>, foreground: Rc<executor::Foreground>,
lifecycle: Rc<dyn platform::Lifecycle>,
platform: Rc<dyn platform::Platform>, platform: Rc<dyn platform::Platform>,
asset_source: impl AssetSource, asset_source: impl AssetSource,
) -> Self { ) -> Self {
let fonts = platform.fonts(); let fonts = platform.fonts();
Self { Self {
weak_self: None, weak_self: None,
lifecycle,
platform, platform,
assets: Arc::new(AssetCache::new(asset_source)), assets: Arc::new(AssetCache::new(asset_source)),
cx: AppContext { cx: AppContext {
@ -704,8 +716,8 @@ impl MutableAppContext {
result result
} }
pub fn set_menus(&self, menus: Vec<Menu>) { pub fn set_menus(&mut self, menus: Vec<Menu>) {
self.platform.set_menus(menus); self.lifecycle.set_menus(menus);
} }
fn prompt<F>( fn prompt<F>(

View file

@ -27,14 +27,17 @@ use std::{
sync::Arc, sync::Arc,
}; };
pub trait Platform { pub(crate) trait Lifecycle {
fn on_menu_command(&self, callback: Box<dyn FnMut(&str, Option<&dyn Any>)>); fn on_menu_command(&self, callback: Box<dyn FnMut(&str, Option<&dyn Any>)>);
fn on_become_active(&self, callback: Box<dyn FnMut()>); fn on_become_active(&self, callback: Box<dyn FnMut()>);
fn on_resign_active(&self, callback: Box<dyn FnMut()>); fn on_resign_active(&self, callback: Box<dyn FnMut()>);
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>); fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>);
fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>); fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>);
fn set_menus(&self, menus: Vec<Menu>);
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>); fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>);
}
pub trait Platform {
fn dispatcher(&self) -> Arc<dyn Dispatcher>; fn dispatcher(&self) -> Arc<dyn Dispatcher>;
fn fonts(&self) -> Arc<dyn FontSystem>; fn fonts(&self) -> Arc<dyn FontSystem>;
@ -59,7 +62,6 @@ pub trait Platform {
fn quit(&self); fn quit(&self);
fn write_to_clipboard(&self, item: ClipboardItem); fn write_to_clipboard(&self, item: ClipboardItem);
fn read_from_clipboard(&self) -> Option<ClipboardItem>; fn read_from_clipboard(&self) -> Option<ClipboardItem>;
fn set_menus(&self, menus: Vec<Menu>);
} }
pub trait Dispatcher: Send + Sync { pub trait Dispatcher: Send + Sync {

View file

@ -11,11 +11,15 @@ mod window;
use cocoa::base::{BOOL, NO, YES}; use cocoa::base::{BOOL, NO, YES};
pub use dispatcher::Dispatcher; pub use dispatcher::Dispatcher;
pub use fonts::FontSystem; pub use fonts::FontSystem;
use platform::MacPlatform; use platform::{MacLifecycle, MacPlatform};
use std::rc::Rc; use std::rc::Rc;
use window::Window; use window::Window;
pub fn platform() -> Rc<dyn super::Platform> { pub(crate) fn lifecycle() -> Rc<dyn super::Lifecycle> {
Rc::new(MacLifecycle::default())
}
pub(crate) fn platform() -> Rc<dyn super::Platform> {
Rc::new(MacPlatform::new()) Rc::new(MacPlatform::new())
} }

View file

@ -32,7 +32,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
const MAC_PLATFORM_IVAR: &'static str = "platform"; const MAC_LIFECYCLE_IVAR: &'static str = "lifecycle";
static mut APP_CLASS: *const Class = ptr::null(); static mut APP_CLASS: *const Class = ptr::null();
static mut APP_DELEGATE_CLASS: *const Class = ptr::null(); static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
@ -40,7 +40,7 @@ static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
unsafe fn build_classes() { unsafe fn build_classes() {
APP_CLASS = { APP_CLASS = {
let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap(); let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR); decl.add_ivar::<*mut c_void>(MAC_LIFECYCLE_IVAR);
decl.add_method( decl.add_method(
sel!(sendEvent:), sel!(sendEvent:),
send_event as extern "C" fn(&mut Object, Sel, id), send_event as extern "C" fn(&mut Object, Sel, id),
@ -50,7 +50,7 @@ unsafe fn build_classes() {
APP_DELEGATE_CLASS = { APP_DELEGATE_CLASS = {
let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap(); let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR); decl.add_ivar::<*mut c_void>(MAC_LIFECYCLE_IVAR);
decl.add_method( decl.add_method(
sel!(applicationDidFinishLaunching:), sel!(applicationDidFinishLaunching:),
did_finish_launching as extern "C" fn(&mut Object, Sel, id), did_finish_launching as extern "C" fn(&mut Object, Sel, id),
@ -75,43 +75,26 @@ unsafe fn build_classes() {
} }
} }
pub struct MacPlatform { #[derive(Default)]
dispatcher: Arc<Dispatcher>, pub struct MacLifecycle(RefCell<MacLifecycleState>);
fonts: Arc<FontSystem>,
callbacks: RefCell<Callbacks>,
menu_item_actions: RefCell<Vec<(String, Option<Box<dyn Any>>)>>,
pasteboard: id,
text_hash_pasteboard_type: id,
metadata_pasteboard_type: id,
}
#[derive(Default)] #[derive(Default)]
struct Callbacks { pub struct MacLifecycleState {
become_active: Option<Box<dyn FnMut()>>, become_active: Option<Box<dyn FnMut()>>,
resign_active: Option<Box<dyn FnMut()>>, resign_active: Option<Box<dyn FnMut()>>,
event: Option<Box<dyn FnMut(crate::Event) -> bool>>, event: Option<Box<dyn FnMut(crate::Event) -> bool>>,
menu_command: Option<Box<dyn FnMut(&str, Option<&dyn Any>)>>, menu_command: Option<Box<dyn FnMut(&str, Option<&dyn Any>)>>,
open_files: Option<Box<dyn FnMut(Vec<PathBuf>)>>, open_files: Option<Box<dyn FnMut(Vec<PathBuf>)>>,
finish_launching: Option<Box<dyn FnOnce() -> ()>>, finish_launching: Option<Box<dyn FnOnce() -> ()>>,
menu_actions: Vec<(String, Option<Box<dyn Any>>)>,
} }
impl MacPlatform { impl MacLifecycle {
pub fn new() -> Self {
Self {
dispatcher: Arc::new(Dispatcher),
fonts: Arc::new(FontSystem::new()),
callbacks: Default::default(),
menu_item_actions: Default::default(),
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
metadata_pasteboard_type: unsafe { ns_string("zed-metadata") },
}
}
unsafe fn create_menu_bar(&self, menus: Vec<Menu>) -> id { unsafe fn create_menu_bar(&self, menus: Vec<Menu>) -> id {
let menu_bar = NSMenu::new(nil).autorelease(); let menu_bar = NSMenu::new(nil).autorelease();
let mut menu_item_actions = self.menu_item_actions.borrow_mut(); let mut state = self.0.borrow_mut();
menu_item_actions.clear();
state.menu_actions.clear();
for menu_config in menus { for menu_config in menus {
let menu_bar_item = NSMenuItem::new(nil).autorelease(); let menu_bar_item = NSMenuItem::new(nil).autorelease();
@ -170,9 +153,9 @@ impl MacPlatform {
.autorelease(); .autorelease();
} }
let tag = menu_item_actions.len() as NSInteger; let tag = state.menu_actions.len() as NSInteger;
let _: () = msg_send![item, setTag: tag]; let _: () = msg_send![item, setTag: tag];
menu_item_actions.push((action.to_string(), arg)); state.menu_actions.push((action.to_string(), arg));
} }
} }
@ -185,6 +168,76 @@ impl MacPlatform {
menu_bar menu_bar
} }
}
impl platform::Lifecycle for MacLifecycle {
fn on_become_active(&self, callback: Box<dyn FnMut()>) {
self.0.borrow_mut().become_active = Some(callback);
}
fn on_resign_active(&self, callback: Box<dyn FnMut()>) {
self.0.borrow_mut().resign_active = Some(callback);
}
fn on_event(&self, callback: Box<dyn FnMut(crate::Event) -> bool>) {
self.0.borrow_mut().event = Some(callback);
}
fn on_menu_command(&self, callback: Box<dyn FnMut(&str, Option<&dyn Any>)>) {
self.0.borrow_mut().menu_command = Some(callback);
}
fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>) {
self.0.borrow_mut().open_files = Some(callback);
}
fn set_menus(&self, menus: Vec<Menu>) {
unsafe {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setMainMenu_(self.create_menu_bar(menus));
}
}
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>) {
self.0.borrow_mut().finish_launching = Some(on_finish_launching);
unsafe {
let app: id = msg_send![APP_CLASS, sharedApplication];
let app_delegate: id = msg_send![APP_DELEGATE_CLASS, new];
app.setDelegate_(app_delegate);
let self_ptr = self as *const Self as *const c_void;
(*app).set_ivar(MAC_LIFECYCLE_IVAR, self_ptr);
(*app_delegate).set_ivar(MAC_LIFECYCLE_IVAR, self_ptr);
let pool = NSAutoreleasePool::new(nil);
app.run();
pool.drain();
(*app).set_ivar(MAC_LIFECYCLE_IVAR, null_mut::<c_void>());
(*app.delegate()).set_ivar(MAC_LIFECYCLE_IVAR, null_mut::<c_void>());
}
}
}
pub struct MacPlatform {
dispatcher: Arc<Dispatcher>,
fonts: Arc<FontSystem>,
pasteboard: id,
text_hash_pasteboard_type: id,
metadata_pasteboard_type: id,
}
impl MacPlatform {
pub fn new() -> Self {
Self {
dispatcher: Arc::new(Dispatcher),
fonts: Arc::new(FontSystem::new()),
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
metadata_pasteboard_type: unsafe { ns_string("zed-metadata") },
}
}
unsafe fn read_from_pasteboard(&self, kind: id) -> Option<&[u8]> { unsafe fn read_from_pasteboard(&self, kind: id) -> Option<&[u8]> {
let data = self.pasteboard.dataForType(kind); let data = self.pasteboard.dataForType(kind);
@ -200,47 +253,6 @@ impl MacPlatform {
} }
impl platform::Platform for MacPlatform { impl platform::Platform for MacPlatform {
fn on_become_active(&self, callback: Box<dyn FnMut()>) {
self.callbacks.borrow_mut().become_active = Some(callback);
}
fn on_resign_active(&self, callback: Box<dyn FnMut()>) {
self.callbacks.borrow_mut().resign_active = Some(callback);
}
fn on_event(&self, callback: Box<dyn FnMut(crate::Event) -> bool>) {
self.callbacks.borrow_mut().event = Some(callback);
}
fn on_menu_command(&self, callback: Box<dyn FnMut(&str, Option<&dyn Any>)>) {
self.callbacks.borrow_mut().menu_command = Some(callback);
}
fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>) {
self.callbacks.borrow_mut().open_files = Some(callback);
}
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>) {
self.callbacks.borrow_mut().finish_launching = Some(on_finish_launching);
unsafe {
let app: id = msg_send![APP_CLASS, sharedApplication];
let app_delegate: id = msg_send![APP_DELEGATE_CLASS, new];
app.setDelegate_(app_delegate);
let self_ptr = self as *const Self as *const c_void;
(*app).set_ivar(MAC_PLATFORM_IVAR, self_ptr);
(*app_delegate).set_ivar(MAC_PLATFORM_IVAR, self_ptr);
let pool = NSAutoreleasePool::new(nil);
app.run();
pool.drain();
(*app).set_ivar(MAC_PLATFORM_IVAR, null_mut::<c_void>());
(*app.delegate()).set_ivar(MAC_PLATFORM_IVAR, null_mut::<c_void>());
}
}
fn dispatcher(&self) -> Arc<dyn platform::Dispatcher> { fn dispatcher(&self) -> Arc<dyn platform::Dispatcher> {
self.dispatcher.clone() self.dispatcher.clone()
} }
@ -434,26 +446,19 @@ impl platform::Platform for MacPlatform {
} }
} }
} }
fn set_menus(&self, menus: Vec<Menu>) {
unsafe {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setMainMenu_(self.create_menu_bar(menus));
}
}
} }
unsafe fn get_platform(object: &mut Object) -> &MacPlatform { unsafe fn get_lifecycle(object: &mut Object) -> &MacLifecycle {
let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR); let platform_ptr: *mut c_void = *object.get_ivar(MAC_LIFECYCLE_IVAR);
assert!(!platform_ptr.is_null()); assert!(!platform_ptr.is_null());
&*(platform_ptr as *const MacPlatform) &*(platform_ptr as *const MacLifecycle)
} }
extern "C" fn send_event(this: &mut Object, _sel: Sel, native_event: id) { extern "C" fn send_event(this: &mut Object, _sel: Sel, native_event: id) {
unsafe { unsafe {
if let Some(event) = Event::from_native(native_event, None) { if let Some(event) = Event::from_native(native_event, None) {
let platform = get_platform(this); let platform = get_lifecycle(this);
if let Some(callback) = platform.callbacks.borrow_mut().event.as_mut() { if let Some(callback) = platform.0.borrow_mut().event.as_mut() {
if callback(event) { if callback(event) {
return; return;
} }
@ -469,23 +474,24 @@ extern "C" fn did_finish_launching(this: &mut Object, _: Sel, _: id) {
let app: id = msg_send![APP_CLASS, sharedApplication]; let app: id = msg_send![APP_CLASS, sharedApplication];
app.setActivationPolicy_(NSApplicationActivationPolicyRegular); app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
let platform = get_platform(this); let platform = get_lifecycle(this);
if let Some(callback) = platform.callbacks.borrow_mut().finish_launching.take() { let callback = platform.0.borrow_mut().finish_launching.take();
if let Some(callback) = callback {
callback(); callback();
} }
} }
} }
extern "C" fn did_become_active(this: &mut Object, _: Sel, _: id) { extern "C" fn did_become_active(this: &mut Object, _: Sel, _: id) {
let platform = unsafe { get_platform(this) }; let platform = unsafe { get_lifecycle(this) };
if let Some(callback) = platform.callbacks.borrow_mut().become_active.as_mut() { if let Some(callback) = platform.0.borrow_mut().become_active.as_mut() {
callback(); callback();
} }
} }
extern "C" fn did_resign_active(this: &mut Object, _: Sel, _: id) { extern "C" fn did_resign_active(this: &mut Object, _: Sel, _: id) {
let platform = unsafe { get_platform(this) }; let platform = unsafe { get_lifecycle(this) };
if let Some(callback) = platform.callbacks.borrow_mut().resign_active.as_mut() { if let Some(callback) = platform.0.borrow_mut().resign_active.as_mut() {
callback(); callback();
} }
} }
@ -506,19 +512,19 @@ extern "C" fn open_files(this: &mut Object, _: Sel, _: id, paths: id) {
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
}; };
let platform = unsafe { get_platform(this) }; let platform = unsafe { get_lifecycle(this) };
if let Some(callback) = platform.callbacks.borrow_mut().open_files.as_mut() { if let Some(callback) = platform.0.borrow_mut().open_files.as_mut() {
callback(paths); callback(paths);
} }
} }
extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) { extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) {
unsafe { unsafe {
let platform = get_platform(this); let platform = get_lifecycle(this);
if let Some(callback) = platform.callbacks.borrow_mut().menu_command.as_mut() { if let Some(callback) = platform.0.borrow_mut().menu_command.as_mut() {
let tag: NSInteger = msg_send![item, tag]; let tag: NSInteger = msg_send![item, tag];
let index = tag as usize; let index = tag as usize;
if let Some((action, arg)) = platform.menu_item_actions.borrow().get(index) { if let Some((action, arg)) = platform.0.borrow_mut().menu_actions.get(index) {
callback(action, arg.as_ref().map(Box::as_ref)); callback(action, arg.as_ref().map(Box::as_ref));
} }
} }

View file

@ -8,6 +8,8 @@ use std::{
sync::Arc, sync::Arc,
}; };
pub(crate) struct Lifecycle;
pub(crate) struct Platform { pub(crate) struct Platform {
dispatcher: Arc<dyn super::Dispatcher>, dispatcher: Arc<dyn super::Dispatcher>,
fonts: Arc<dyn super::FontSystem>, fonts: Arc<dyn super::FontSystem>,
@ -27,6 +29,24 @@ pub struct Window {
pub(crate) last_prompt: RefCell<Option<Box<dyn FnOnce(usize)>>>, pub(crate) last_prompt: RefCell<Option<Box<dyn FnOnce(usize)>>>,
} }
impl super::Lifecycle for Lifecycle {
fn on_menu_command(&self, _: Box<dyn FnMut(&str, Option<&dyn Any>)>) {}
fn on_become_active(&self, _: Box<dyn FnMut()>) {}
fn on_resign_active(&self, _: Box<dyn FnMut()>) {}
fn on_event(&self, _: Box<dyn FnMut(crate::Event) -> bool>) {}
fn on_open_files(&self, _: Box<dyn FnMut(Vec<std::path::PathBuf>)>) {}
fn set_menus(&self, _: Vec<crate::Menu>) {}
fn run(&self, _on_finish_launching: Box<dyn FnOnce() -> ()>) {
unimplemented!()
}
}
impl Platform { impl Platform {
fn new() -> Self { fn new() -> Self {
Self { Self {
@ -54,20 +74,6 @@ impl Platform {
} }
impl super::Platform for Platform { impl super::Platform for Platform {
fn on_menu_command(&self, _: Box<dyn FnMut(&str, Option<&dyn Any>)>) {}
fn on_become_active(&self, _: Box<dyn FnMut()>) {}
fn on_resign_active(&self, _: Box<dyn FnMut()>) {}
fn on_event(&self, _: Box<dyn FnMut(crate::Event) -> bool>) {}
fn on_open_files(&self, _: Box<dyn FnMut(Vec<std::path::PathBuf>)>) {}
fn run(&self, _on_finish_launching: Box<dyn FnOnce() -> ()>) {
unimplemented!()
}
fn dispatcher(&self) -> Arc<dyn super::Dispatcher> { fn dispatcher(&self) -> Arc<dyn super::Dispatcher> {
self.dispatcher.clone() self.dispatcher.clone()
} }
@ -91,8 +97,6 @@ impl super::Platform for Platform {
None None
} }
fn set_menus(&self, _menus: Vec<crate::Menu>) {}
fn quit(&self) {} fn quit(&self) {}
fn prompt_for_paths( fn prompt_for_paths(
@ -175,6 +179,10 @@ impl super::Window for Window {
} }
} }
pub(crate) fn lifecycle() -> Lifecycle {
Lifecycle
}
pub(crate) fn platform() -> Platform { pub(crate) fn platform() -> Platform {
Platform::new() Platform::new()
} }