src/osx.rs
//! fruitbasket - Framework for running Rust programs in a Mac 'app bundle' environment.
//!
//! fruitbasket provides two different (but related) services for helping you run your
//! Rust binaries as native AppKit/Cocoa applications on Mac OS X:
//!
//! * App lifecycle and environment API - fruitbasket provides an API to initialize the
//! AppKit application environment (NSApplication), to pump the main application loop
//! and dispatch Apple events in a non-blocking way, to terminate the application, to
//! access resources in the app bundle, and various other tasks frequently needed by
//! Mac applications.
//!
//! * Self-bundling app 'trampoline' - fruitbasket provides a 'trampoline' to
//! automatically bundle a standalone binary as a Mac application in a `.app` bundle
//! at runtime. This allows access to features that require running from a bundle (
//! such as XPC services), self-installing into the Applications folder, registering
//! your app with the system as a document type or URL handler, and various other
//! features that are only available to bundled apps with unique identifiers.
//! Self-bundling and relaunching itself (the "trampoline" behavior) allows your app
//! to get the features of app bundles, but still be launched in the standard Rust
//! ways (such as `cargo run`).
//!
//! The primary goal of fruitbasket is to make it reasonably easy to develop native
//! Mac GUI applications with the standard Apple AppKit/Cocoa/Foundation frameworks
//! in pure Rust by pushing all of the Apple and Objective-C runtime logic into
//! dedicated libraries, isolating the logic of a Rust binary application from the
//! unsafe platform code. As the ecosystem of Mac libraries for Rust grows, you
//! should be able to mix-and-match the libraries your application needs, pump the
//! event loop with fruitbasket, and never worry about Objective-C in your application.
//!
//! # Getting Started
//!
//! You likely want to create either a [Trampoline](struct.Trampoline.html) or a
//! [FruitApp](struct.FruitApp.html) right after your Rust application starts.
//! If uncertain, use a `Trampoline`. You can hit very strange behavior when running
//! Cocoa apps outside of an app bundle.
// Temporarily (mmmmhmm...) disable deprecated function warnings, because objc macros
// throw tons of them in rustc 1.34-nightly when initializing atomic uints.
use std;
use thread;
use Duration;
use Path;
use PathBuf;
use Write;
use Cell;
use channel;
use Receiver;
use Sender;
use HashMap;
use FruitError;
use ActivationPolicy;
use RunPeriod;
use InstallDir;
use FruitStopper;
use DEFAULT_PLIST;
use FORBIDDEN_PLIST;
extern crate time;
extern crate dirs;
extern crate objc;
use Object;
use Class;
extern crate objc_id;
use Id;
use WeakId;
use Shared;
extern crate objc_foundation;
use ;
use Message;
use ClassDecl;
use ;
use ;
const nil: *mut Object = 0 as *mut Object;
extern
/// Main interface for controlling and interacting with the AppKit app
///
/// `FruitApp` is an instance of an AppKit app, equivalent to (and containing)
/// the NSApplication singleton that is responsible for the app's lifecycle
/// and participation in the Mac app ecosystem.
///
/// You must initialize a single instance of FruitApp before using any Apple
/// frameworks, and after creating it you must regularly pump its event loop.
///
/// You must follow all of the standard requirements for NSApplication. Most
/// notably: FruitApp **must** be created on your app's main thread, and **must**
/// be pumped from the same main thread. Doing otherwise angers the beast.
///
/// An application does *not* need to be in a Mac app bundle to run, so this can
/// be created in any application with [FruitApp::new](FruitApp::new). However, many Apple
/// frameworks *do* require the application to be running from a bundle, so you
/// may want to consider creating your FruitApp instance from the [Trampoline](Trampoline)
/// struct's builder instead.
///
/// A boxed Fn type for receiving Rust callbacks from ObjC events
pub type FruitObjcCallback<'a> = ;
/// Key into the ObjC callback hash map
///
/// You can register to receive callbacks from ObjectiveC based on these keys.
///
/// Callbacks that are not tied to objects can be registered with static
/// selector strings. For instance, if your app has registered itself as a URL
/// handler, you would use:
/// FruitCallbackKey::Method("handleEvent:withReplyEvent:")
///
/// Other pre-defined selectors are:
/// FruitCallbackKey::Method("applicationWillFinishlaunching:")
/// FruitCallbackKey::Method("applicationDidFinishlaunching:")
///
/// The Object variant is currently unused, and reserved for the future.
/// If the callback will be from a particular object, you use the Object type
/// with the ObjC object included. For example, if you want to register for
/// callbacks from a particular NSButton instance, you would add it to the
/// callback map with:
/// let button1: *mut Object = <create an NSButton>;
/// app.register_callback(FruitCallbackKey::Object(button),
/// Box::new(|button1| {
/// println!("got callback from button1, address: {:x}", button1 as u64);
/// }));
///
/// Rust class for wrapping Objective-C callback class
///
/// There is one Objective-C object, implemented in Rust but registered with and
/// owned by the Objective-C runtime, which handles ObjC callbacks such as those
/// for the NSApplication delegate. This is a native Rust class that wraps the
/// ObjC object.
///
/// There should be exactly one of this object, and it must be stored on the
/// heap (i.e. in a Box). This is because the ObjC object calls into this class
/// via raw function pointers, and its address must not change.
///
/// API to move the executable into a Mac app bundle and relaunch (if necessary)
///
/// `Trampoline` is a builder pattern for creating a `FruitApp` application
/// instance that is guaranteed to be running inside a Mac app bundle. See the
/// module documentation for why this is often important.
///
/// If the currently running process is already in an app bundle, Trampoline
/// does nothing and is equivalent to calling [FruitApp::new](FruitApp::new).
///
/// The builder takes a variety of information that is required for creating a
/// Mac app (notably: app name, executable name, unique identifier), as well
/// as optional metadata to describe your app and its interactions to the OS,
/// and optional file resources to bundle with it. It creates an app bundle,
/// either in an install path of your choosing or in a temporary directory,
/// launches the bundled app, and terminates the non-bundled binary.
///
/// Care should be taken to call this very early in your application, since any
/// work done prior to this will be discarded when the app is relaunched. Your
/// program should also gracefully support relaunching from a different directory.
/// Take care not to perform any actions that would prevent relaunching, such as
/// claiming locks, until after the trampoline.
///
/// Parse an Apple URL event into a URL string
///
/// Takes an NSAppleEventDescriptor from an Apple URL event, unwraps
/// it, and returns the contained URL as a String.
/// Convert an NSString to a Rust `String`
/// ObjcSubclass is a subclass of the objective-c NSObject base class.
/// This is registered with the objc runtime, so instances of this class
/// are "owned" by objc, and have no associated Rust data.
///
/// This can be wrapped with a ObjcWrapper, which is a proper Rust struct
/// with its own storage, and holds an instance of ObjcSubclass.
///
/// An ObjcSubclass can "talk" to its Rust wrapper class through function
/// pointers, as long as the storage is on the heap with a Box and the underlying
/// memory address doesn't change.
///
unsafe
static OBJC_SUBCLASS_REGISTER_CLASS: Once = ONCE_INIT;
/// Define an ObjC class and register it with the ObjC runtime