rust_macios/appkit/
ns_application.rs1use std::{fmt, marker::PhantomData, sync::Once};
2
3use objc::{
4 class,
5 declare::ClassDecl,
6 msg_send,
7 runtime::{Class, Object},
8 sel, sel_impl,
9};
10use objc_id::Id;
11
12use crate::{
13 objective_c_runtime::{
14 id,
15 traits::{FromId, PNSObject, ToId},
16 },
17 utils::to_bool,
18};
19
20use super::{
21 ns_application_delegate::PNSApplicationDelegate, register_app_delegate_class, INSResponder,
22 NSApplicationActivationPolicy, NSApplicationDelegateReply, NSMenu,
23};
24pub static NSAPPLICATION_PTR: &str = "rstNSApplicationPtr";
26
27fn register_app_class() -> *const Class {
28 static mut APP_CLASS: *const Class = 0 as *const Class;
29 static INIT: Once = Once::new();
30
31 INIT.call_once(|| unsafe {
32 let superclass = class!(NSApplication);
33 let decl = ClassDecl::new("RSTNSApplication", superclass).unwrap();
34 APP_CLASS = decl.register();
35 });
36
37 unsafe { APP_CLASS }
38}
39
40pub struct NSApplication<'app, M = ()> {
42 pub ptr: Id<Object>,
44 _message: PhantomData<&'app M>,
45}
46
47pub trait INSApplication: INSResponder {
50 fn p_shared_application() -> Self
52 where
53 Self: Sized + FromId,
54 {
55 unsafe { Self::from_id(msg_send![Self::m_class(), sharedApplication]) }
56 }
57
58 fn p_delegate(&self) -> id {
60 unsafe { msg_send![self.m_self(), delegate] }
61 }
62
63 fn p_set_delegate<'app, T>(&'app mut self, app_delegate: T)
65 where
66 T: PNSApplicationDelegate + 'app,
67 {
68 unsafe {
69 let delegate_class = register_app_delegate_class::<T>();
70 let delegate: id = msg_send![delegate_class, new];
71 let delegate_ptr: *const T = &app_delegate;
72 (*delegate).set_ivar(NSAPPLICATION_PTR, delegate_ptr as usize);
73 msg_send![self.m_self(), setDelegate: delegate]
74 }
75 }
76
77 fn p_running(&self) -> bool {
82 unsafe { msg_send![self.m_self(), isRunning] }
83 }
84
85 fn m_run(&self) {
87 unsafe { msg_send![self.m_self(), run] }
88 }
89
90 fn m_finish_launching(&self) {
92 unsafe { msg_send![self.m_self(), finishLaunching] }
93 }
94
95 fn m_stop(&self, sender: id) {
97 unsafe { msg_send![self.m_self(), stop: sender] }
98 }
99
100 fn m_terminate(&self, sender: id) {
105 unsafe { msg_send![self.m_self(), terminate: sender] }
106 }
107
108 fn m_reply_to_application_should_terminate(&self, should_terminate: bool) {
110 unsafe {
111 msg_send![
112 self.m_self(),
113 replyToApplicationShouldTerminate: should_terminate
114 ]
115 }
116 }
117
118 fn p_active(&self) -> bool {
123 unsafe { to_bool(msg_send![self.m_self(), isActive]) }
124 }
125
126 fn m_activate_ignoring_other_apps(&mut self, flag: bool) {
128 unsafe { msg_send![self.m_self(), activateIgnoringOtherApps: flag] }
129 }
130
131 fn m_deactivate(&mut self) {
133 unsafe { msg_send![self.m_self(), deactivate] }
134 }
135
136 fn m_disable_relaunch_on_login(&mut self) {
141 unsafe { msg_send![self.m_self(), disableRelaunchOnLogin] }
142 }
143
144 fn m_enable_relaunch_on_login(&mut self) {
146 unsafe { msg_send![self.m_self(), enableRelaunchOnLogin] }
147 }
148
149 fn m_register_for_remote_notifications(&mut self) {
154 unsafe { msg_send![self.m_self(), registerForRemoteNotifications] }
155 }
156
157 fn m_unregister_for_remote_notifications(&mut self) {
159 unsafe { msg_send![self.m_self(), unregisterForRemoteNotifications] }
160 }
161
162 fn m_reply_to_open_or_print(&self, response: NSApplicationDelegateReply) {
167 unsafe { msg_send![self.m_self(), replyToOpenOrPrint: response] }
168 }
169
170 fn m_activation_policy(&self) -> NSApplicationActivationPolicy {
175 unsafe { msg_send![self.m_self(), activationPolicy] }
176 }
177
178 fn m_set_activation_policy(&mut self, policy: NSApplicationActivationPolicy) {
184 unsafe { msg_send![self.m_self(), setActivationPolicy: policy] }
185 }
186
187 fn p_main_menu(&self) -> NSMenu {
191 unsafe { msg_send![self.m_self(), mainMenu] }
192 }
193
194 fn p_set_main_menu(&mut self, menu: NSMenu) {
196 unsafe { msg_send![self.m_self(), setMainMenu: menu] }
197 }
198}
199
200impl<'app> NSApplication<'app> {
201 pub fn shared_application() -> NSApplication<'app> {
203 NSApplication::p_shared_application()
204 }
205
206 pub fn delegate(&self) -> id {
208 self.p_delegate()
209 }
210}
211
212impl NSApplication<'_> {
213 pub fn running(&self) -> bool {
215 self.p_running()
216 }
217
218 pub fn run(&mut self) {
220 self.m_run();
221 }
222
223 pub fn finish_launching(&mut self) {
225 self.m_finish_launching()
226 }
227
228 pub fn stop(&mut self, sender: id) {
230 self.m_stop(sender)
231 }
232
233 pub fn terminate(&mut self, sender: id) {
235 self.m_terminate(sender)
236 }
237
238 pub fn reply_to_application_should_terminate(&self, should_terminate: bool) {
240 self.m_reply_to_application_should_terminate(should_terminate)
241 }
242
243 pub fn disable_relaunch_on_login(&mut self) {
245 self.m_disable_relaunch_on_login()
246 }
247
248 pub fn enable_relaunch_on_login(&mut self) {
250 self.m_enable_relaunch_on_login()
251 }
252
253 pub fn register_for_remote_notifications(&mut self) {
255 self.m_register_for_remote_notifications()
256 }
257
258 pub fn unregister_for_remote_notifications(&mut self) {
260 self.m_unregister_for_remote_notifications()
261 }
262
263 pub fn reply_to_open_or_print(&self, response: NSApplicationDelegateReply) {
265 self.m_reply_to_open_or_print(response)
266 }
267
268 pub fn activation_policy(&self) -> NSApplicationActivationPolicy {
270 self.m_activation_policy()
271 }
272
273 pub fn set_activation_policy(&mut self, policy: NSApplicationActivationPolicy) {
279 self.m_set_activation_policy(policy)
280 }
281
282 pub fn main_menu(&self) -> NSMenu {
284 self.p_main_menu()
285 }
286
287 pub fn set_main_menu(&mut self, menu: NSMenu) {
289 self.p_set_main_menu(menu)
290 }
291}
292
293impl NSApplication<'_> {
294 pub fn new() -> Self {
296 let ptr = unsafe {
297 let app: id = msg_send![register_app_class(), sharedApplication];
298 Id::from_ptr(app)
299 };
300
301 Self {
302 ptr,
303 _message: PhantomData,
304 }
305 }
306}
307
308impl Default for NSApplication<'_> {
309 fn default() -> Self {
310 Self::new()
311 }
312}
313
314impl PNSObject for NSApplication<'_> {
315 fn m_class<'a>() -> &'a Class {
316 unsafe { &*register_app_class() }
317 }
318
319 fn m_self(&self) -> id {
320 unsafe { msg_send![&*self.ptr, self] }
321 }
322}
323
324impl INSResponder for NSApplication<'_> {}
325
326impl INSApplication for NSApplication<'_> {}
327
328impl fmt::Debug for NSApplication<'_> {
329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330 write!(f, "{}", self.p_debug_description())
331 }
332}
333
334impl ToId for NSApplication<'_> {
335 fn to_id(mut self) -> id {
336 &mut *self.ptr
337 }
338}
339
340impl FromId for NSApplication<'_> {
341 unsafe fn from_id(ptr: id) -> Self {
342 Self {
343 ptr: Id::from_ptr(ptr),
344 _message: PhantomData,
345 }
346 }
347}