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