1#![cfg(target_os = "macos")]
2mod dispatcher;
8mod display;
9mod display_link;
10mod events;
11mod keyboard;
12mod pasteboard;
13mod system_notifications;
14
15#[cfg(feature = "screen-capture")]
16mod screen_capture;
17
18use gpui_apple::metal_renderer as renderer;
19
20pub mod metal_renderer {
21 pub use gpui_apple::metal_renderer::{PathRasterizationVertex, PathSprite, SurfaceBounds};
22
23 #[cfg(any(test, feature = "bench-support", feature = "test-support"))]
24 pub use gpui_apple::metal_renderer::MetalHeadlessRenderer;
25}
26
27#[cfg(feature = "font-kit")]
28mod open_type;
29
30#[cfg(feature = "font-kit")]
31mod text_system;
32
33mod platform;
34mod window;
35mod window_appearance;
36
37use cocoa::{
38 base::{id, nil},
39 foundation::{NSAutoreleasePool, NSNotFound, NSString, NSUInteger},
40};
41
42use objc::runtime::{BOOL, NO, YES};
43use std::{
44 ffi::{CStr, c_char},
45 ops::Range,
46};
47
48pub(crate) use dispatcher::*;
49pub(crate) use display::*;
50pub(crate) use display_link::*;
51pub(crate) use keyboard::*;
52pub(crate) use platform::*;
53pub(crate) use window::*;
54
55#[cfg(feature = "font-kit")]
56pub(crate) use text_system::*;
57
58pub use platform::MacPlatform;
59
60trait BoolExt {
61 fn to_objc(self) -> BOOL;
62}
63
64impl BoolExt for bool {
65 fn to_objc(self) -> BOOL {
66 if self { YES } else { NO }
67 }
68}
69
70trait NSStringExt {
71 unsafe fn to_str(&self) -> &str;
72}
73
74impl NSStringExt for id {
75 unsafe fn to_str(&self) -> &str {
76 unsafe {
77 let cstr = self.UTF8String();
78 if cstr.is_null() {
79 ""
80 } else {
81 CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
82 }
83 }
84 }
85}
86
87#[repr(C)]
88#[derive(Copy, Clone, Debug)]
89struct NSRange {
90 pub location: NSUInteger,
91 pub length: NSUInteger,
92}
93
94impl NSRange {
95 fn invalid() -> Self {
96 Self {
97 location: NSNotFound as NSUInteger,
98 length: 0,
99 }
100 }
101
102 fn is_valid(&self) -> bool {
103 self.location != NSNotFound as NSUInteger
104 }
105
106 fn to_range(self) -> Option<Range<usize>> {
107 if self.is_valid() {
108 let start = self.location as usize;
109 let end = start + self.length as usize;
110 Some(start..end)
111 } else {
112 None
113 }
114 }
115}
116
117impl From<Range<usize>> for NSRange {
118 fn from(range: Range<usize>) -> Self {
119 NSRange {
120 location: range.start as NSUInteger,
121 length: range.len() as NSUInteger,
122 }
123 }
124}
125
126unsafe impl objc::Encode for NSRange {
127 fn encode() -> objc::Encoding {
128 let encoding = format!(
129 "{{NSRange={}{}}}",
130 NSUInteger::encode().as_str(),
131 NSUInteger::encode().as_str()
132 );
133 unsafe { objc::Encoding::from_str(&encoding) }
134 }
135}
136
137#[allow(clippy::disallowed_methods)]
139unsafe fn ns_string(string: &str) -> id {
140 unsafe { NSString::alloc(nil).init_str(string).autorelease() }
141}