1use super::{BoolExt as _, Dispatcher, FontSystem, Window};
2use crate::{executor, platform};
3use anyhow::Result;
4use cocoa::{
5 appkit::{NSPasteboard, NSPasteboardTypeString},
6 base::{id, nil},
7 foundation::NSData,
8};
9use objc::{class, msg_send, sel, sel_impl};
10use std::{ffi::c_void, rc::Rc, sync::Arc};
11
12pub struct App {
13 dispatcher: Arc<Dispatcher>,
14 fonts: Arc<FontSystem>,
15}
16
17impl App {
18 pub fn new() -> Self {
19 Self {
20 dispatcher: Arc::new(Dispatcher),
21 fonts: Arc::new(FontSystem::new()),
22 }
23 }
24}
25
26impl platform::App for App {
27 fn dispatcher(&self) -> Arc<dyn platform::Dispatcher> {
28 self.dispatcher.clone()
29 }
30
31 fn activate(&self, ignoring_other_apps: bool) {
32 unsafe {
33 let app: id = msg_send![class!(NSApplication), sharedApplication];
34 let _: () = msg_send![app, activateIgnoringOtherApps: ignoring_other_apps.to_objc()];
35 }
36 }
37
38 fn open_window(
39 &self,
40 options: platform::WindowOptions,
41 executor: Rc<executor::Foreground>,
42 ) -> Result<Box<dyn platform::Window>> {
43 Ok(Box::new(Window::open(options, executor, self.fonts())?))
44 }
45
46 fn fonts(&self) -> Arc<dyn platform::FontSystem> {
47 self.fonts.clone()
48 }
49
50 fn copy(&self, text: &str) {
51 unsafe {
52 let data = NSData::dataWithBytes_length_(
53 nil,
54 text.as_ptr() as *const c_void,
55 text.len() as u64,
56 );
57 let pasteboard = NSPasteboard::generalPasteboard(nil);
58 pasteboard.clearContents();
59 pasteboard.setData_forType(data, NSPasteboardTypeString);
60 }
61 }
62}