commit: | 7db3c18b5a7c8bcade41c94b3757e04759df4f4e |
author: | Trevor Bentley |
committer: | GitHub |
date: | Sat Mar 20 19:26:45 2021 +0100 |
parents: | 9956b66760de76b5f013e7e6161517100cdd7148, 305136ac4816d266f41438570aa63778807d8bf3 |
diff --git a/examples/register_url.rs b/examples/register_url.rs line changes: +13/-1 index 7a135d8..9ca9aec --- a/examples/register_url.rs +++ b/examples/register_url.rs
@@ -102,7 +102,19 @@ CFBundleURLTypes = ( { stopper.stop(); })); - // Run 'forever', until the URL callback fires + let stopper = app.stopper(); + app.register_callback( + FruitCallbackKey::Method("application:openFile:"), + Box::new(move |file| { + // File is a raw NSString. + // Fruitbasket has a converter to Rust String: + let file: String = fruitbasket::nsstring_to_string(file); + info!("Received file: {}", file); + stopper.stop(); + }), + ); + + // Run 'forever', until one of the URL or file callbacks fire info!("Spawned process running!"); let _ = app.run(RunPeriod::Forever); info!("Run loop stopped after URL callback.");
diff --git a/src/lib.rs b/src/lib.rs line changes: +9/-0 index cbd0825..ceab61a --- a/src/lib.rs +++ b/src/lib.rs
@@ -120,6 +120,9 @@ pub use osx::FruitCallbackKey; #[cfg(all(target_os = "macos", not(feature="dummy")))] pub use osx::parse_url_event; +#[cfg(all(target_os = "macos", not(feature="dummy")))] +pub use osx::nsstring_to_string; + #[cfg(any(not(target_os = "macos"), feature="dummy"))] /// Docs in OS X build. pub enum FruitCallbackKey {
@@ -196,6 +199,12 @@ impl FruitApp { /// Docs in OS X build. pub fn parse_url_event(_event: *mut u64) -> String { "".into() } +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] +/// Docs in OS X build. +pub fn nsstring_to_string(_nsstring: *mut u64) -> String { + "".into() +} + /// API to move the executable into a Mac app bundle and relaunch (if necessary) /// /// Dummy implementation for non-OSX platforms. See OS X build for proper
diff --git a/src/osx.rs b/src/osx.rs line changes: +30/-3 index 7bddbaa..b777fe7 --- a/src/osx.rs +++ b/src/osx.rs
@@ -857,13 +857,22 @@ pub fn parse_url_event(event: *mut Object) -> String { } let subevent: *mut Object = msg_send![event, paramDescriptorForKeyword: ::keyDirectObject]; let nsstring: *mut Object = msg_send![subevent, stringValue]; + nsstring_to_string(nsstring) + } +} + +/// Convert an NSString to a Rust `String` +pub fn nsstring_to_string(nsstring: *mut Object) -> String { + unsafe { let cstr: *const i8 = msg_send![nsstring, UTF8String]; if cstr != std::ptr::null() { - let rstr = std::ffi::CStr::from_ptr(cstr).to_string_lossy().into_owned(); - return rstr; + std::ffi::CStr::from_ptr(cstr) + .to_string_lossy() + .into_owned() + } else { + "".into() } } - "".into() } /// ObjcSubclass is a subclass of the objective-c NSObject base class.
@@ -925,6 +934,22 @@ impl INSObject for ObjcSubclass { FruitCallbackKey::Method("applicationWillFinishLaunching:"), event as *mut Object); } + /// NSApplication delegate callback + extern "C" fn objc_open_file( + this: &Object, + _cmd: Sel, + _application: u64, + file: u64, + ) -> bool { + let ptr: u64 = unsafe { *this.get_ivar("_rustwrapper") }; + ObjcSubclass::dispatch_cb( + ptr, + FruitCallbackKey::Method("application:openFile:"), + file as *mut Object, + ); + + true + } /// Register the Rust ObjcWrapper instance that wraps this object /// /// In order for an instance of this ObjC owned object to reach back
@@ -947,6 +972,8 @@ impl INSObject for ObjcSubclass { decl.add_method(sel!(applicationDidFinishLaunching:), f); let f: extern fn(&Object, Sel, u64) = objc_will_finish; decl.add_method(sel!(applicationWillFinishLaunching:), f); + let f: extern "C" fn(&Object, Sel, u64, u64) -> bool = objc_open_file; + decl.add_method(sel!(application:openFile:), f); } decl.register();