diff --git a/examples/example.rs b/examples/example.rs index 6091543e..aac71a35 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -1,50 +1,57 @@ extern crate fruitbasket; use fruitbasket::ActivationPolicy; -use fruitbasket::Trampoline; use fruitbasket::FruitApp; +use fruitbasket::FruitError; use fruitbasket::InstallDir; use fruitbasket::RunPeriod; -use fruitbasket::FruitError; -use std::time::Duration; +use fruitbasket::Trampoline; use std::path::PathBuf; +use std::time::Duration; #[macro_use] extern crate log; fn main() { - let _ = fruitbasket::create_logger(".fruitbasket.log", fruitbasket::LogDir::Home, 5, 2).unwrap(); + let _ = + fruitbasket::create_logger(".fruitbasket.log", fruitbasket::LogDir::Home, 5, 2).unwrap(); // Find the icon file from the Cargo project dir let icon = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("examples").join("icon.png"); + .join("examples") + .join("icon.png"); // Re-launch self in an app bundle if not already running from one. info!("Executable must run from App bundle. Let's try:"); - let mut app = match Trampoline::new("fruitbasket", "fruitbasket", "com.trevorbentley.fruitbasket") - .version("2.1.3") - .icon("fruitbasket.icns") - .plist_key("CFBundleSpokenName","\"fruit basket\"") - .plist_keys(&vec![ - ("LSMinimumSystemVersion", "10.12.0"), - ("LSBackgroundOnly", "1"), - ]) - .resource(icon.to_str().unwrap()) - .build(InstallDir::Temp) { - Err(FruitError::UnsupportedPlatform(_)) => { - info!("This is not a Mac. App bundling is not supported."); - info!("It is still safe to use FruitApp::new(), though the dummy app will do nothing."); - FruitApp::new() - }, - Err(FruitError::IOError(e)) => { - info!("IO error! {}", e); - std::process::exit(1); - }, - Err(FruitError::GeneralError(e)) => { - info!("General error! {}", e); - std::process::exit(1); - }, - Ok(app) => app, - }; + let mut app = match Trampoline::new( + "fruitbasket", + "fruitbasket", + "com.trevorbentley.fruitbasket", + ) + .version("2.1.3") + .icon("fruitbasket.icns") + .plist_key("CFBundleSpokenName", "\"fruit basket\"") + .plist_keys(&vec![ + ("LSMinimumSystemVersion", "10.12.0"), + ("LSBackgroundOnly", "1"), + ]) + .resource(icon.to_str().unwrap()) + .build(InstallDir::Temp) + { + Err(FruitError::UnsupportedPlatform(_)) => { + info!("This is not a Mac. App bundling is not supported."); + info!("It is still safe to use FruitApp::new(), though the dummy app will do nothing."); + FruitApp::new() + } + Err(FruitError::IOError(e)) => { + info!("IO error! {}", e); + std::process::exit(1); + } + Err(FruitError::GeneralError(e)) => { + info!("General error! {}", e); + std::process::exit(1); + } + Ok(app) => app, + }; // App is guaranteed to be running in a bundle now! diff --git a/examples/register_url.rs b/examples/register_url.rs index 7a135d8f..db7ad614 100644 --- a/examples/register_url.rs +++ b/examples/register_url.rs @@ -13,58 +13,73 @@ /// extern crate fruitbasket; use fruitbasket::ActivationPolicy; -use fruitbasket::Trampoline; use fruitbasket::FruitApp; +use fruitbasket::FruitCallbackKey; +use fruitbasket::FruitError; use fruitbasket::InstallDir; use fruitbasket::RunPeriod; -use fruitbasket::FruitError; -use fruitbasket::FruitCallbackKey; +use fruitbasket::Trampoline; use std::path::PathBuf; #[macro_use] extern crate log; fn main() { - let _ = fruitbasket::create_logger(".fruitbasket_register_url.log", fruitbasket::LogDir::Home, 5, 2).unwrap(); + let _ = fruitbasket::create_logger( + ".fruitbasket_register_url.log", + fruitbasket::LogDir::Home, + 5, + 2, + ) + .unwrap(); // Find the icon file from the Cargo project dir let icon = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("examples").join("icon.png"); + .join("examples") + .join("icon.png"); // Re-launch self in an app bundle if not already running from one. info!("Executable must run from App bundle. Let's try:"); - let mut app = match Trampoline::new("fruitbasket_register_url", "fruitbasket", "com.trevorbentley.fruitbasket_register_url") - .version("2.1.3") - .icon("fruitbasket.icns") - .plist_key("CFBundleSpokenName","\"fruit basket\"") - .plist_keys(&vec![ - ("LSMinimumSystemVersion", "10.12.0"), - ("LSBackgroundOnly", "1"), - ]) - // Register "fruitbasket://" and "fbasket://" URL schemes in Info.plist - .plist_raw_string(" + let mut app = match Trampoline::new( + "fruitbasket_register_url", + "fruitbasket", + "com.trevorbentley.fruitbasket_register_url", + ) + .version("2.1.3") + .icon("fruitbasket.icns") + .plist_key("CFBundleSpokenName", "\"fruit basket\"") + .plist_keys(&vec![ + ("LSMinimumSystemVersion", "10.12.0"), + ("LSBackgroundOnly", "1"), + ]) + // Register "fruitbasket://" and "fbasket://" URL schemes in Info.plist + .plist_raw_string( + " CFBundleURLTypes = ( { CFBundleTypeRole = \"Viewer\"; CFBundleURLName = \"Fruitbasket Example URL\"; CFBundleURLSchemes = (\"fruitbasket\", \"fbasket\"); -} );\n".into()) - .resource(icon.to_str().unwrap()) - .build(InstallDir::Temp) { - Err(FruitError::UnsupportedPlatform(_)) => { - info!("This is not a Mac. App bundling is not supported."); - info!("It is still safe to use FruitApp::new(), though the dummy app will do nothing."); - FruitApp::new() - }, - Err(FruitError::IOError(e)) => { - info!("IO error! {}", e); - std::process::exit(1); - }, - Err(FruitError::GeneralError(e)) => { - info!("General error! {}", e); - std::process::exit(1); - }, - Ok(app) => app, - }; +} );\n" + .into(), + ) + .resource(icon.to_str().unwrap()) + .build(InstallDir::Temp) + { + Err(FruitError::UnsupportedPlatform(_)) => { + info!("This is not a Mac. App bundling is not supported."); + info!("It is still safe to use FruitApp::new(), though the dummy app will do nothing."); + FruitApp::new() + } + Err(FruitError::IOError(e)) => { + info!("IO error! {}", e); + std::process::exit(1); + } + Err(FruitError::GeneralError(e)) => { + info!("General error! {}", e); + std::process::exit(1); + } + Ok(app) => app, + }; // App is guaranteed to be running in a bundle now! @@ -79,11 +94,13 @@ CFBundleURLTypes = ( { // Register a callback for when the ObjC application finishes launching let stopper = app.stopper(); - app.register_callback(FruitCallbackKey::Method("applicationWillFinishLaunching:"), - Box::new(move |_event| { - info!("applicationDidFinishLaunching."); - stopper.stop(); - })); + app.register_callback( + FruitCallbackKey::Method("applicationWillFinishLaunching:"), + Box::new(move |_event| { + info!("applicationDidFinishLaunching."); + stopper.stop(); + }), + ); // Run until callback is called info!("Spawned process started. Run until applicationDidFinishLaunching."); @@ -93,14 +110,16 @@ CFBundleURLTypes = ( { // Register a callback to get receive custom URL schemes from any Mac program app.register_apple_event(fruitbasket::kInternetEventClass, fruitbasket::kAEGetURL); let stopper = app.stopper(); - app.register_callback(FruitCallbackKey::Method("handleEvent:withReplyEvent:"), - Box::new(move |event| { - // Event is a raw NSAppleEventDescriptor. - // Fruitbasket has a parser for URLs. Call that to get the URL: - let url: String = fruitbasket::parse_url_event(event); - info!("Received URL: {}", url); - stopper.stop(); - })); + app.register_callback( + FruitCallbackKey::Method("handleEvent:withReplyEvent:"), + Box::new(move |event| { + // Event is a raw NSAppleEventDescriptor. + // Fruitbasket has a parser for URLs. Call that to get the URL: + let url: String = fruitbasket::parse_url_event(event); + info!("Received URL: {}", url); + stopper.stop(); + }), + ); // Run 'forever', until the URL callback fires info!("Spawned process running!"); diff --git a/src/lib.rs b/src/lib.rs index cfc71f66..a0aad278 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,18 +36,18 @@ #![deny(missing_docs)] use std::error::Error; -use std::time::Duration; use std::sync::mpsc::Sender; +use std::time::Duration; -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] use std::sync::mpsc::Receiver; -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] use std::thread; -extern crate time; extern crate dirs; +extern crate time; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] #[macro_use] extern crate objc; @@ -72,10 +72,10 @@ macro_rules! info { /// default values provided here, but can be overridden by your application with /// the Trampoline builder's `plist_key*()` functions. pub const DEFAULT_PLIST: &'static [(&'static str, &'static str)] = &[ - ("CFBundleInfoDictionaryVersion","6.0"), - ("CFBundlePackageType","APPL"), - ("CFBundleSignature","xxxx"), - ("LSMinimumSystemVersion","10.10.0"), + ("CFBundleInfoDictionaryVersion", "6.0"), + ("CFBundlePackageType", "APPL"), + ("CFBundleSignature", "xxxx"), + ("LSMinimumSystemVersion", "10.10.0"), ]; /// Info.plist entries that are set, and cannot be overridden @@ -83,7 +83,7 @@ pub const DEFAULT_PLIST: &'static [(&'static str, &'static str)] = &[ /// These properties are always set in the app bundle's Property List, based on /// information provided to the Trampoline builder, and cannot be overridden /// with the builder's `plist_key*()` functions. -pub const FORBIDDEN_PLIST: &'static [&'static str] = & [ +pub const FORBIDDEN_PLIST: &'static [&'static str] = &[ "CFBundleName", "CFBundleDisplayName", "CFBundleIdentifier", @@ -102,25 +102,25 @@ pub const kAEGetURL: u32 = 0x4755524c; #[allow(non_upper_case_globals)] pub const keyDirectObject: u32 = 0x2d2d2d2d; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] mod osx; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] pub use osx::FruitApp; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] pub use osx::Trampoline; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] pub use osx::FruitObjcCallback; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] pub use osx::FruitCallbackKey; -#[cfg(all(target_os = "macos", not(feature="dummy")))] +#[cfg(all(target_os = "macos", not(feature = "dummy")))] pub use osx::parse_url_event; -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] /// Docs in OS X build. pub enum FruitCallbackKey { /// Docs in OS X build. @@ -129,7 +129,7 @@ pub enum FruitCallbackKey { Object(*mut u64), } -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] /// Docs in OS X build. pub type FruitObjcCallback = Box; @@ -137,18 +137,18 @@ pub type FruitObjcCallback = Box; /// /// Dummy implementation for non-OSX platforms. See OS X build for proper /// documentation. -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] pub struct FruitApp { tx: Sender<()>, rx: Receiver<()>, } -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] impl FruitApp { /// Docs in OS X build. pub fn new() -> FruitApp { use std::sync::mpsc::channel; - let (tx,rx) = channel(); - FruitApp{ tx: tx, rx: rx} + let (tx, rx) = channel(); + FruitApp { tx: tx, rx: rx } } /// Docs in OS X build. pub fn register_callback(&mut self, _key: FruitCallbackKey, _cb: FruitObjcCallback) {} @@ -165,7 +165,7 @@ impl FruitApp { stopper.stop(); } /// Docs in OS X build. - pub fn run(&mut self, period: RunPeriod) -> Result<(),()> { + pub fn run(&mut self, period: RunPeriod) -> Result<(), ()> { let start = time::now_utc().to_timespec(); loop { if self.rx.try_recv().is_ok() { @@ -186,52 +186,84 @@ impl FruitApp { } /// Docs in OS X build. pub fn stopper(&self) -> FruitStopper { - FruitStopper { tx: self.tx.clone() } + FruitStopper { + tx: self.tx.clone(), + } } /// Docs in OS X build. - pub fn bundled_resource_path(_name: &str, _extension: &str) -> Option { None } + pub fn bundled_resource_path(_name: &str, _extension: &str) -> Option { + None + } } -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] /// Docs in OS X build. -pub fn parse_url_event(_event: *mut u64) -> String { "".into() } +pub fn parse_url_event(_event: *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 /// documentation. -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] pub struct Trampoline {} -#[cfg(any(not(target_os = "macos"), feature="dummy"))] +#[cfg(any(not(target_os = "macos"), feature = "dummy"))] impl Trampoline { /// Docs in OS X build. - pub fn new(_name: &str, _exe: &str, _ident: &str) -> Trampoline { Trampoline {} } + pub fn new(_name: &str, _exe: &str, _ident: &str) -> Trampoline { + Trampoline {} + } /// Docs in OS X build. - pub fn name(&mut self, _name: &str) -> &mut Self { self } + pub fn name(&mut self, _name: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn exe(&mut self, _exe: &str) -> &mut Self { self } + pub fn exe(&mut self, _exe: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn ident(&mut self, _ident: &str) -> &mut Self { self } + pub fn ident(&mut self, _ident: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn icon(&mut self, _icon: &str) -> &mut Self { self } + pub fn icon(&mut self, _icon: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn version(&mut self, _version: &str) -> &mut Self { self } + pub fn version(&mut self, _version: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn plist_key(&mut self, _key: &str, _value: &str) -> &mut Self { self } + pub fn plist_key(&mut self, _key: &str, _value: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn plist_keys(&mut self, _pairs: &Vec<(&str,&str)>) -> &mut Self { self } + pub fn plist_keys(&mut self, _pairs: &Vec<(&str, &str)>) -> &mut Self { + self + } /// Docs in OS X build. - pub fn plist_raw_string(&mut self, _s: String) -> &mut Self { self } + pub fn plist_raw_string(&mut self, _s: String) -> &mut Self { + self + } /// Docs in OS X build. - pub fn resource(&mut self, _file: &str) -> &mut Self { self } + pub fn resource(&mut self, _file: &str) -> &mut Self { + self + } /// Docs in OS X build. - pub fn resources(&mut self, _files: &Vec<&str>) -> &mut Self{ self } + pub fn resources(&mut self, _files: &Vec<&str>) -> &mut Self { + self + } /// Docs in OS X build. pub fn build(&mut self, _dir: InstallDir) -> Result { - Err(FruitError::UnsupportedPlatform("fruitbasket disabled or not supported on this platform.".to_string())) + Err(FruitError::UnsupportedPlatform( + "fruitbasket disabled or not supported on this platform.".to_string(), + )) } /// Docs in OS X build. - pub fn is_bundled() -> bool { false } + pub fn is_bundled() -> bool { + false + } } /// Options for how long to run the event loop on each call @@ -361,18 +393,20 @@ pub enum LogDir { /// /// Full path to opened log file on disk #[cfg(feature = "logging")] -pub fn create_logger(filename: &str, - dir: LogDir, - max_size_mb: u32, - backup_count: u32) -> Result { - use log::LevelFilter; +pub fn create_logger( + filename: &str, + dir: LogDir, + max_size_mb: u32, + backup_count: u32, +) -> Result { use self::log4rs::append::console::ConsoleAppender; - use self::log4rs::append::rolling_file::RollingFileAppender; - use self::log4rs::append::rolling_file::policy::compound::CompoundPolicy; use self::log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller; use self::log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger; - use self::log4rs::encode::pattern::PatternEncoder; + use self::log4rs::append::rolling_file::policy::compound::CompoundPolicy; + use self::log4rs::append::rolling_file::RollingFileAppender; use self::log4rs::config::{Appender, Config, Logger, Root}; + use self::log4rs::encode::pattern::PatternEncoder; + use log::LevelFilter; let log_path = match dir { LogDir::Home => format!("{}/{}", dirs::home_dir().unwrap().display(), filename), @@ -382,9 +416,12 @@ pub fn create_logger(filename: &str, let stdout = ConsoleAppender::builder() .encoder(Box::new(PatternEncoder::new("{m}{n}"))) .build(); - let trigger = Box::new(SizeTrigger::new(1024*1024*max_size_mb as u64)); - let roller = Box::new(FixedWindowRoller::builder() - .build(&format!("{}.{{}}", log_path), backup_count).unwrap()); + let trigger = Box::new(SizeTrigger::new(1024 * 1024 * max_size_mb as u64)); + let roller = Box::new( + FixedWindowRoller::builder() + .build(&format!("{}.{{}}", log_path), backup_count) + .unwrap(), + ); let policy = Box::new(CompoundPolicy::new(trigger, roller)); let rolling = RollingFileAppender::builder() .build(&log_path, policy) @@ -394,11 +431,18 @@ pub fn create_logger(filename: &str, .appender(Appender::builder().build("stdout", Box::new(stdout))) .appender(Appender::builder().build("requests", Box::new(rolling))) .logger(Logger::builder().build("app::backend::db", LevelFilter::Info)) - .logger(Logger::builder() + .logger( + Logger::builder() .appender("requests") .additive(false) - .build("app::requests", LevelFilter::Info)) - .build(Root::builder().appender("stdout").appender("requests").build(LevelFilter::Info)) + .build("app::requests", LevelFilter::Info), + ) + .build( + Root::builder() + .appender("stdout") + .appender("requests") + .build(LevelFilter::Info), + ) .unwrap(); match log4rs::init_config(config) { Ok(_) => Ok(log_path), @@ -439,9 +483,13 @@ pub fn create_logger(filename: &str, /// /// Full path to opened log file on disk #[cfg(not(feature = "logging"))] -pub fn create_logger(_filename: &str, - _dir: LogDir, - _max_size_mb: u32, - _backup_count: u32) -> Result { - Err(FruitError::GeneralError("Must recompile with 'logging' feature to use logger.".to_string())) +pub fn create_logger( + _filename: &str, + _dir: LogDir, + _max_size_mb: u32, + _backup_count: u32, +) -> Result { + Err(FruitError::GeneralError( + "Must recompile with 'logging' feature to use logger.".to_string(), + )) } diff --git a/src/osx.rs b/src/osx.rs index 867ef3b4..6238d9eb 100644 --- a/src/osx.rs +++ b/src/osx.rs @@ -40,22 +40,22 @@ #![allow(deprecated)] use std; -use std::thread; -use std::time::Duration; +use std::cell::Cell; +use std::collections::HashMap; +use std::io::Write; use std::path::Path; use std::path::PathBuf; -use std::io::Write; -use std::cell::Cell; use std::sync::mpsc::channel; use std::sync::mpsc::Receiver; use std::sync::mpsc::Sender; -use std::collections::HashMap; +use std::thread; +use std::time::Duration; -use super::FruitError; use super::ActivationPolicy; -use super::RunPeriod; -use super::InstallDir; +use super::FruitError; use super::FruitStopper; +use super::InstallDir; +use super::RunPeriod; use super::DEFAULT_PLIST; use super::FORBIDDEN_PLIST; @@ -64,21 +64,20 @@ extern crate time; extern crate dirs; extern crate objc; -use objc::runtime::Object; use objc::runtime::Class; +use objc::runtime::Object; extern crate objc_id; use self::objc_id::Id; -use self::objc_id::WeakId; use self::objc_id::Shared; +use self::objc_id::WeakId; extern crate objc_foundation; -use std::sync::{Once, ONCE_INIT}; -use objc::Message; -use objc::declare::ClassDecl; -use objc::runtime::{Sel}; use self::objc_foundation::{INSObject, NSObject}; - +use objc::declare::ClassDecl; +use objc::runtime::Sel; +use objc::Message; +use std::sync::{Once, ONCE_INIT}; #[allow(non_upper_case_globals)] const nil: *mut Object = 0 as *mut Object; @@ -87,7 +86,7 @@ const nil: *mut Object = 0 as *mut Object; #[link(name = "CoreFoundation", kind = "framework")] #[link(name = "ApplicationServices", kind = "framework")] #[link(name = "AppKit", kind = "framework")] -extern {} +extern "C" {} /// Main interface for controlling and interacting with the AppKit app /// @@ -205,7 +204,7 @@ pub struct Trampoline { ident: String, icon: String, version: String, - keys: Vec<(String,String)>, + keys: Vec<(String, String)>, plist_raw_strings: Vec, resources: Vec, } @@ -245,8 +244,7 @@ impl Trampoline { exe: exe.to_string(), ident: ident.to_string(), version: "1.0.0".to_string(), - .. - Default::default() + ..Default::default() } } /// Set name of application. Same as provided to `new()`. @@ -324,7 +322,7 @@ impl Trampoline { /// /// See documentation of [plist_key()](Trampoline::plist_key). This function does the same, but /// allows specifying more than one key/value pair at a time. - pub fn plist_keys(&mut self, pairs: &Vec<(&str,&str)>) -> &mut Self { + pub fn plist_keys(&mut self, pairs: &Vec<(&str, &str)>) -> &mut Self { for &(ref key, ref value) in pairs { self.keys.push((key.to_string(), value.to_string())); } @@ -367,7 +365,7 @@ impl Trampoline { /// /// See documentation of [resource()](Trampoline::resource). This function does the same, but /// allows specifying more than one resource at a time. - pub fn resources(&mut self, files: &Vec<&str>) -> &mut Self{ + pub fn resources(&mut self, files: &Vec<&str>) -> &mut Self { for file in files { self.resources.push(file.to_string()); } @@ -480,7 +478,7 @@ impl Trampoline { } // Default fields (if user didn't override) - let keys: Vec<&str> = self.keys.iter().map(|x| {x.0.as_ref()}).collect(); + let keys: Vec<&str> = self.keys.iter().map(|x| x.0.as_ref()).collect(); for &(ref key, ref val) in DEFAULT_PLIST { if !keys.contains(key) { write!(&mut f, " {} = {};\n", key, val)?; @@ -505,7 +503,7 @@ impl Trampoline { initWithBytes:app.as_ptr() length:app.len() encoding: 4]; // UTF8_ENCODING - let _:() = msg_send![wspace, launchApplication: s]; + let _: () = msg_send![wspace, launchApplication: s]; // Note: launchedApplication doesn't return until the child process // calls [NSApplication sharedApplication]. @@ -526,7 +524,7 @@ impl FruitApp { /// /// A newly allocated FruitApp for managing the app pub fn new() -> FruitApp { - let (tx,rx) = channel::<()>(); + let (tx, rx) = channel::<()>(); unsafe { let cls = Class::get("NSApplication").unwrap(); let app: *mut Object = msg_send![cls, sharedApplication]; @@ -546,7 +544,7 @@ impl FruitApp { map: HashMap::new(), }); let ptr: u64 = &*rustobjc as *const ObjcWrapper as u64; - let _:() = msg_send![rustobjc.objc, setRustWrapper: ptr]; + let _: () = msg_send![rustobjc.objc, setRustWrapper: ptr]; FruitApp { app: app, pool: Cell::new(pool), @@ -586,7 +584,7 @@ impl FruitApp { let cls = Class::get("NSAppleEventManager").unwrap(); let manager: *mut Object = msg_send![cls, sharedAppleEventManager]; let objc = (*self.objc).take(); - let _:() = msg_send![manager, + let _: () = msg_send![manager, setEventHandler: objc andSelector: sel!(handleEvent:withReplyEvent:) forEventClass: class @@ -602,7 +600,7 @@ impl FruitApp { ActivationPolicy::Prohibited => 2, }; unsafe { - let _:() = msg_send![self.app, setActivationPolicy: policy_int]; + let _: () = msg_send![self.app, setActivationPolicy: policy_int]; } } @@ -625,7 +623,7 @@ impl FruitApp { unsafe { let cls = objc::runtime::Class::get("NSApplication").unwrap(); let app: *mut objc::runtime::Object = msg_send![cls, sharedApplication]; - let _:() = msg_send![app, terminate: exit_code]; + let _: () = msg_send![app, terminate: exit_code]; } } @@ -661,7 +659,7 @@ impl FruitApp { /// # Returns /// /// Ok on natural end, Err if stopped by a Stopper. - pub fn run(&mut self, period: RunPeriod) -> Result<(),()>{ + pub fn run(&mut self, period: RunPeriod) -> Result<(), ()> { let start = time::now_utc().to_timespec(); loop { if self.rx.try_recv().is_ok() { @@ -673,14 +671,14 @@ impl FruitApp { let cls = objc::runtime::Class::get("NSApplication").unwrap(); let app: *mut objc::runtime::Object = msg_send![cls, sharedApplication]; let objc = (*self.objc).take(); - let _:() = msg_send![app, setDelegate: objc]; - let _:() = msg_send![self.app, finishLaunching]; + let _: () = msg_send![app, setDelegate: objc]; + let _: () = msg_send![self.app, finishLaunching]; } // Create a new release pool every once in a while, draining the old one if run_count % 100 == 0 { let old_pool = self.pool.get(); if run_count != 0 { - let _:() = msg_send![old_pool, drain]; + let _: () = msg_send![old_pool, drain]; } let cls = Class::get("NSAutoreleasePool").unwrap(); let pool: *mut Object = msg_send![cls, alloc]; @@ -693,8 +691,8 @@ impl FruitApp { untilDate: nil inMode: mode dequeue: 1]; - let _:() = msg_send![self.app, sendEvent: event]; - let _:() = msg_send![self.app, updateWindows]; + let _: () = msg_send![self.app, sendEvent: event]; + let _: () = msg_send![self.app, updateWindows]; self.run_count.set(run_count + 1); } if period == RunPeriod::Once { @@ -727,7 +725,7 @@ impl FruitApp { /// cloned infinite times.. pub fn stopper(&self) -> FruitStopper { FruitStopper { - tx: self.tx.clone() + tx: self.tx.clone(), } } @@ -764,11 +762,13 @@ impl FruitApp { let ini: *mut Object = msg_send![bundle, pathForResource:objc_name ofType:objc_ext]; - let _:() = msg_send![objc_name, release]; - let _:() = msg_send![objc_ext, release]; + let _: () = msg_send![objc_name, release]; + let _: () = msg_send![objc_ext, release]; let cstr: *const i8 = msg_send![ini, UTF8String]; if cstr != std::ptr::null() { - let rstr = std::ffi::CStr::from_ptr(cstr).to_string_lossy().into_owned(); + let rstr = std::ffi::CStr::from_ptr(cstr) + .to_string_lossy() + .into_owned(); return Some(rstr); } None @@ -794,7 +794,9 @@ pub fn parse_url_event(event: *mut Object) -> String { let nsstring: *mut Object = msg_send![subevent, stringValue]; 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(); + let rstr = std::ffi::CStr::from_ptr(cstr) + .to_string_lossy() + .into_owned(); return rstr; } } @@ -814,7 +816,7 @@ pub fn parse_url_event(event: *mut Object) -> String { /// enum ObjcSubclass {} -unsafe impl Message for ObjcSubclass { } +unsafe impl Message for ObjcSubclass {} static OBJC_SUBCLASS_REGISTER_CLASS: Once = ONCE_INIT; @@ -840,25 +842,31 @@ impl INSObject for ObjcSubclass { decl.add_ivar::("_rustwrapper"); /// Callback for events from Apple's NSAppleEventManager - extern fn objc_apple_event(this: &Object, _cmd: Sel, event: u64, _reply: u64) { + extern "C" fn objc_apple_event(this: &Object, _cmd: Sel, event: u64, _reply: u64) { let ptr: u64 = unsafe { *this.get_ivar("_rustwrapper") }; - ObjcSubclass::dispatch_cb(ptr, - FruitCallbackKey::Method("handleEvent:withReplyEvent:"), - event as *mut Object); + ObjcSubclass::dispatch_cb( + ptr, + FruitCallbackKey::Method("handleEvent:withReplyEvent:"), + event as *mut Object, + ); } /// NSApplication delegate callback - extern fn objc_did_finish(this: &Object, _cmd: Sel, event: u64) { + extern "C" fn objc_did_finish(this: &Object, _cmd: Sel, event: u64) { let ptr: u64 = unsafe { *this.get_ivar("_rustwrapper") }; - ObjcSubclass::dispatch_cb(ptr, - FruitCallbackKey::Method("applicationDidFinishLaunching:"), - event as *mut Object); + ObjcSubclass::dispatch_cb( + ptr, + FruitCallbackKey::Method("applicationDidFinishLaunching:"), + event as *mut Object, + ); } /// NSApplication delegate callback - extern fn objc_will_finish(this: &Object, _cmd: Sel, event: u64) { + extern "C" fn objc_will_finish(this: &Object, _cmd: Sel, event: u64) { let ptr: u64 = unsafe { *this.get_ivar("_rustwrapper") }; - ObjcSubclass::dispatch_cb(ptr, - FruitCallbackKey::Method("applicationWillFinishLaunching:"), - event as *mut Object); + ObjcSubclass::dispatch_cb( + ptr, + FruitCallbackKey::Method("applicationWillFinishLaunching:"), + event as *mut Object, + ); } /// Register the Rust ObjcWrapper instance that wraps this object /// @@ -869,18 +877,20 @@ impl INSObject for ObjcSubclass { /// in memory. The address of this wrapping struct is given to this /// object by casting the Box into a raw pointer, and then casting /// that into a u64, which is stored here. - extern fn objc_set_rust_wrapper(this: &mut Object, _cmd: Sel, ptr: u64) { - unsafe {this.set_ivar("_rustwrapper", ptr);} + extern "C" fn objc_set_rust_wrapper(this: &mut Object, _cmd: Sel, ptr: u64) { + unsafe { + this.set_ivar("_rustwrapper", ptr); + } } unsafe { // Register all of the above handlers as true ObjC selectors: - let f: extern fn(&mut Object, Sel, u64) = objc_set_rust_wrapper; + let f: extern "C" fn(&mut Object, Sel, u64) = objc_set_rust_wrapper; decl.add_method(sel!(setRustWrapper:), f); - let f: extern fn(&Object, Sel, u64, u64) = objc_apple_event; + let f: extern "C" fn(&Object, Sel, u64, u64) = objc_apple_event; decl.add_method(sel!(handleEvent:withReplyEvent:), f); - let f: extern fn(&Object, Sel, u64) = objc_did_finish; + let f: extern "C" fn(&Object, Sel, u64) = objc_did_finish; decl.add_method(sel!(applicationDidFinishLaunching:), f); - let f: extern fn(&Object, Sel, u64) = objc_will_finish; + let f: extern "C" fn(&Object, Sel, u64) = objc_will_finish; decl.add_method(sel!(applicationWillFinishLaunching:), f); }