macos.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use objc2::{ DefinedClass, MainThreadOnly, define_class, msg_send }; use objc2::rc::{ Retained }; use objc2::runtime::{ ProtocolObject }; use objc2_foundation::{ MainThreadMarker, NSNotification, NSObject, NSObjectProtocol, NSPoint, NSRect, NSSize, ns_string, }; use objc2_app_kit::{ NSApplication, NSApplicationDelegate, NSApplicationActivationPolicy, NSBackingStoreType, NSWindow, NSWindowDelegate, NSWindowStyleMask, }; use std::cell::{ OnceCell }; #[derive(Debug, Default)] struct CrucibleDelegateIvars { window: OnceCell<Retained<NSWindow>>, } define_class!{ #[unsafe(super = NSObject)] #[thread_kind = MainThreadOnly] #[ivars = CrucibleDelegateIvars] struct CrucibleDelegate; unsafe impl NSObjectProtocol for CrucibleDelegate {} unsafe impl NSApplicationDelegate for CrucibleDelegate { #[unsafe(method(applicationDidFinishLaunching:))] fn did_finish_launching(&self, notification: &NSNotification) { let mtm = self.mtm(); let application = unsafe { notification.object() .expect("applicationDidFinishLaunching notification should have an object") .downcast::<NSApplication>() .expect("applicationDidFinishLaunching notification object should be an NSApplication") }; let window = unsafe { let content_rect = NSRect::new( NSPoint::new(0.0, 0.0), NSSize::new(1280.0, 720.0) ); let style_mask = NSWindowStyleMask::Titled | NSWindowStyleMask::Closable | NSWindowStyleMask::Miniaturizable | NSWindowStyleMask::Resizable; NSWindow::initWithContentRect_styleMask_backing_defer( NSWindow::alloc(mtm), content_rect, style_mask, NSBackingStoreType::Buffered, false ) }; unsafe { window.setReleasedWhenClosed(false) }; window.setTitle(ns_string!("Crucible Application")); window.center(); window.setDelegate(Some(ProtocolObject::from_ref(self))); window.makeKeyAndOrderFront(None); self .ivars() .window .set(window) .expect("Should have been able to set window as an ivar"); application.setActivationPolicy(NSApplicationActivationPolicy::Regular); #[allow(deprecated)] application.activateIgnoringOtherApps(true); } } unsafe impl NSWindowDelegate for CrucibleDelegate { #[unsafe(method(windowWillClose:))] fn window_will_close(&self, _notification: &NSNotification) { unsafe { NSApplication::sharedApplication(self.mtm()) .terminate(None) }; } } } impl CrucibleDelegate { pub fn new(mtm: MainThreadMarker) -> Retained<CrucibleDelegate> { let this = CrucibleDelegate::alloc(mtm) .set_ivars(CrucibleDelegateIvars::default()); unsafe { msg_send![super(this), init] } } } pub fn run() { let mtm = MainThreadMarker::new() .expect("Must be called from the main thread"); let application = NSApplication::sharedApplication(mtm); let delegate = CrucibleDelegate::new(mtm); application.setDelegate(Some(ProtocolObject::from_ref(&*delegate))); application.run(); }