Expand description

Cacao

This library provides safe Rust bindings for AppKit on appkit and (eventually) UIKit on uikit and tvOS. It tries to do so in a way that, if you’ve done programming for the framework before (in Swift or Objective-C), will feel familiar. This is tricky in Rust due to the ownership model, but some creative coding and assumptions can get us pretty far.

This library is currently very early stage and may have bugs. Your usage of it is at your own risk. With that said, provided you follow the rules (regarding memory/ownership) it’s already fine for some apps.

Note that this crate relies on the Objective-C runtime. Interfacing with the runtime requires unsafe blocks; this crate handles those unsafe interactions for you and provides a mostly safe wrapper, but by using this crate you understand that usage of unsafe is a given and will be somewhat rampant for wrapped controls. This does not mean you can’t assess, review, or question unsafe usage - just know it’s happening, and in large part it’s not going away.

Hello World

use cacao::appkit::{App, AppDelegate};
use cacao::appkit::window::Window;

#[derive(Default)]
struct BasicApp {
    window: Window
}

impl AppDelegate for BasicApp {
    fn did_finish_launching(&self) {
       self.window.set_minimum_content_size(400., 400.);
       self.window.set_title("Hello World!");
       self.window.show();
    }
}

fn main() {
    App::new("com.hello.world", BasicApp::default()).run();
}

Initialization

Due to the way that AppKit and UIKit programs typically work, you’re encouraged to do the bulk of your work starting from the did_finish_launching() method of your AppDelegate. This ensures the application has had time to initialize and do any housekeeping necessary behind the scenes.

Note that, in order for this framework to be useful, you must always elect one of the following features:

  • appkit: Implements appkit-specific APIs (menus, toolbars, windowing, and so on).
  • uikit: Implements uikit-specific APIs (scenes, navigation controllers, and so on).

The rest of the features in this framework attempt to expose a common API across the three aforementioned feature platforms; if you need something else, you can often implement it yourself by accessing the underlying objc property of a control and sending messages to it directly.

Optional Features

The following are a list of Cargo features that can be enabled or disabled.

  • autolayout: Enables the use of AutoLayout across all widget types. This is a default feature, but is gated to enable platforms that might shim AppKit without AutoLayout support.
  • cloudkit: Links CloudKit.framework and provides some wrappers around CloudKit functionality. Currently not feature complete.
  • color_fallbacks: Provides fallback colors for older systems where systemColor types don’t exist. This feature is very uncommon and you probably don’t need it.
  • quicklook: Links QuickLook.framework and offers methods for generating preview images for files.
  • user-notifications: Links UserNotifications.framework and provides functionality for emitting notifications on appkit and uikit. Note that this requires your application be code-signed, and will not work without it.
  • webview: Links WebKit.framework and provides a WebView control backed by WKWebView. This feature will not be supported on tvOS, as the platform has no webview control.
  • webview-downloading-macos: Enables downloading files from the WebView via a private interface. This is not an App-Store-safe feature, so be aware of that before enabling. This feature is not supported on uikit (a user would handle downloads very differently) or tvOS (there’s no web browser there at all).

Re-exports

pub use core_graphics;
pub use lazy_static;
pub use objc;
pub use url;

Modules

appkitappkit

This module implements the core components necessary for making a well-formed macOS application. These components are ones that are uniquely macOS-specific, and don’t have a true equivalent on iOS and tvOS as the interaction patterns are significantly different.

Wraps NSButton on appkit, and UIButton on iOS and tvOS.

cloudkitcloudkit

This module wraps a portion of the CloudKit API. This is a fairly extensive API, and is not easy to wrap - if you use this and need something that’s not implemented, please consider helping out with an implementation and pull request.

Implements a wrapper type for NSColor and UIColor. It attempts to map to a common shared API, but it’s important to note that the platforms themselves have differing levels of support for color work. Where possible, we expose some platform-specific methods for creating and working with these.

Wraps NSUserDefaults, providing an interface to fetch and store small amounts of data.

This module contains various bits and pieces for drag and drop operations. They’re shared across the codebase, hence why they’re here - they’re not currently exhaustive, so feel free to tinker and pull request.

A wrapper for NSError.

Hoists some type definitions in a way that I personally find cleaner than what’s in the Servo code.

This module contains some lightweight wrappers over Foundation data types.

Wrapper methods for various geometry types (rects, sizes, ec).

Wraps NSTextField and UITextField across platforms, explicitly as a TextField. In AppKit, NSTextField does double duty, and for clarity we just double the implementation.

This provides some basic mapping for providing Key characters to controls. It’s mostly meant as a wrapper to stop magic symbols all over the place.

Wraps CALayer across all platforms.

This module contains traits and helpers for layout. By default, standard frame-based layouts are supported via the Layout trait, which all widgets implement. If you opt in to the AutoLayout feature, each widget will default to using AutoLayout, which can be beneficial in more complicated views that need to deal with differing screen sizes.

Wraps NSView and UIView across platforms.

A lightweight wrapper over some networking components, like NSURLRequest and co.

A wrapper for NSNotificationCenter.

A wrapper for NSPasteBoard, which is the interface for copy/paste and general transferring (think: drag and drop between applications). It exposes a Rust interface that tries to be complete, but might not cover everything 100% right now - feel free to pull request.

A progress indicator widget.

quicklookquicklook

Wraps NSView and UIView across platforms.

Implements a Select-style dropdown. By default this uses NSPopupSelect on macOS.

A wrapper for NSSwitch. Currently the epitome of jank - if you’re poking around here, expect that this will change at some point.

The text module encompasses various widgets for rendering and interacting with text.

uikituikit

iOS-specific implementations.

A module wrapping NSUserActivity.

user_notificationsuser-notifications

Wraps UNUserNotificationCenter for macOS. Note that this uses the newer UserNotifications.framework API, which requires that your application be properly signed.

Utils is a dumping ground for various methods that don’t really have a particular module they belong to. These are typically internal, and if you rely on them… well, don’t be surprised if they go away one day.

Wraps NSView and UIView across platforms.

webviewwebview

Wraps WKWebView across all platforms.