Skip to content

Instantly share code, notes, and snippets.

@kettle11
Last active July 31, 2020 20:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kettle11/3934c29c16b4b9893cee1a45d8a88b02 to your computer and use it in GitHub Desktop.
Save kettle11/3934c29c16b4b9893cee1a45d8a88b02 to your computer and use it in GitHub Desktop.
The minimal amount of code required to create a window on MacOS from Rust
use objc::runtime::{Object, NO};
use objc::*;
// We must link with AppKit for all application and windowing related matters.
#[link(name = "AppKit", kind = "framework")]
extern "C" {}
// https://developer.apple.com/documentation/objectivec/nsuinteger
#[cfg(target_pointer_width = "32")]
pub type NSUInteger = u32;
#[cfg(target_pointer_width = "64")]
pub type NSUInteger = u64;
// https://developer.apple.com/documentation/coregraphics/cgfloat?language=objc
#[cfg(target_pointer_width = "32")]
pub type CGFloat = f32;
#[cfg(target_pointer_width = "64")]
pub type CGFloat = f64;
// https://developer.apple.com/documentation/coregraphics/cgpoint?language=objc
#[repr(C)]
pub struct CGPoint {
pub x: CGFloat,
pub y: CGFloat,
}
// https://developer.apple.com/documentation/coregraphics/cgsize?language=objc
#[repr(C)]
pub struct CGSize {
pub width: CGFloat,
pub height: CGFloat,
}
// https://developer.apple.com/documentation/coregraphics/cgrect?language=objc
#[repr(C)]
pub struct CGRect {
pub origin: CGPoint,
pub size: CGSize,
}
// https://developer.apple.com/documentation/foundation/nsrect?language=objc
pub type NSRect = CGRect;
// https://developer.apple.com/documentation/objectivec/nil
pub const nil: *mut Object = 0 as *mut Object;
// https://developer.apple.com/documentation/appkit/nsapplicationactivationpolicy/nsapplicationactivationpolicyregular?language=objc
pub const NSApplicationActivationPolicyRegular: NSUInteger = 0;
// https://developer.apple.com/documentation/appkit/nsbackingstoretype/nsbackingstorebuffered?language=objc
pub const NSBackingStoreBuffered: NSUInteger = 2;
// https://developer.apple.com/documentation/appkit/nswindowstylemask
pub const NSWindowStyleMaskTitled: NSUInteger = 1;
pub const NSWindowStyleMaskClosable: NSUInteger = 1 << 1;
pub const NSWindowStyleMaskMiniaturizable: NSUInteger = 1 << 2;
pub const NSWindowStyleMaskResizable: NSUInteger = 1 << 3;
unsafe fn setup_application() {
// https://developer.apple.com/documentation/appkit/nsapplication
// Retrieve the global 'sharedApplication'
let ns_application: *mut Object = msg_send![class!(NSApplication), sharedApplication];
// https://developer.apple.com/documentation/appkit/nsapplicationactivationpolicy/nsapplicationactivationpolicyregular?language=objc
// "The application is an ordinary app that appears in the Dock and may have a user interface."
// Apple claims this is the default, but without manually setting it the application does not appear.
//
// Objective-C works with a message passing system. The 'msg_send!' macro abstracts some of the details of the
// message passing system and requires a peculiar syntax.
// The first item in msg_send! is the item being sent the message.
// The following items are the names of the parameters followed by the argument.
// A quirk of the `objc` crate is that it needs to know the return type of the msg_send!
// call. So even though nothing is returned that must be specified with `let () = `.
let () = msg_send![
ns_application,
setActivationPolicy: NSApplicationActivationPolicyRegular
];
// Allocate the window before we initialize it.
let ns_window: *mut Object = msg_send![class!(NSWindow), alloc];
// The size and location of the window we're about to create.
let window_rectangle = NSRect {
origin: CGPoint { x: 0., y: 0. },
size: CGSize {
width: 500.,
height: 500.,
},
};
// We'd like a window that is resizable, has a title, is closable, and can be minimized.
let style = NSWindowStyleMaskResizable
| NSWindowStyleMaskTitled
| NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable;
// https://developer.apple.com/documentation/appkit/nswindow/1419477-initwithcontentrect?language=objc
// Initialize the window with our settings.
let () = msg_send![
ns_window,
initWithContentRect: window_rectangle
styleMask: style
backing:NSBackingStoreBuffered // The Apple recommended setting. See above documentation link for more info.
defer:NO // Create the window immediately.
];
// https://developer.apple.com/documentation/appkit/nswindow/1419208-makekeyandorderfront?language=objc
// This call actually displays the window. Without it the window won't appear
let () = msg_send![ns_window, makeKeyAndOrderFront: nil];
// Run the application forever
let () = msg_send![ns_application, run];
}
fn main() {
unsafe {
setup_application();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment