1//! Macos screen have a y axis that goings up from the bottom of the screen and
2//! an origin at the bottom left of the main display.
3mod dispatcher;
4mod display;
5mod display_link;
6mod events;
7
8#[cfg(not(feature = "macos-blade"))]
9mod metal_atlas;
10#[cfg(not(feature = "macos-blade"))]
11pub mod metal_renderer;
12
13#[cfg(not(feature = "macos-blade"))]
14use metal_renderer as renderer;
15
16#[cfg(feature = "macos-blade")]
17use crate::platform::blade as renderer;
18
19mod open_type;
20mod platform;
21mod text_system;
22mod window;
23mod window_appearance;
24
25use crate::{px, size, DevicePixels, Pixels, Size};
26use cocoa::{
27 base::{id, nil},
28 foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger},
29};
30
31use objc::runtime::{BOOL, NO, YES};
32use std::{
33 ffi::{c_char, CStr},
34 ops::Range,
35};
36
37pub(crate) use dispatcher::*;
38pub(crate) use display::*;
39pub(crate) use display_link::*;
40pub(crate) use platform::*;
41pub(crate) use text_system::*;
42pub(crate) use window::*;
43
44trait BoolExt {
45 fn to_objc(self) -> BOOL;
46}
47
48impl BoolExt for bool {
49 fn to_objc(self) -> BOOL {
50 if self {
51 YES
52 } else {
53 NO
54 }
55 }
56}
57
58trait NSStringExt {
59 unsafe fn to_str(&self) -> &str;
60}
61
62impl NSStringExt for id {
63 unsafe fn to_str(&self) -> &str {
64 let cstr = self.UTF8String();
65 if cstr.is_null() {
66 ""
67 } else {
68 CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
69 }
70 }
71}
72
73#[repr(C)]
74#[derive(Copy, Clone, Debug)]
75struct NSRange {
76 pub location: NSUInteger,
77 pub length: NSUInteger,
78}
79
80impl NSRange {
81 fn invalid() -> Self {
82 Self {
83 location: NSNotFound as NSUInteger,
84 length: 0,
85 }
86 }
87
88 fn is_valid(&self) -> bool {
89 self.location != NSNotFound as NSUInteger
90 }
91
92 fn to_range(self) -> Option<Range<usize>> {
93 if self.is_valid() {
94 let start = self.location as usize;
95 let end = start + self.length as usize;
96 Some(start..end)
97 } else {
98 None
99 }
100 }
101}
102
103impl From<Range<usize>> for NSRange {
104 fn from(range: Range<usize>) -> Self {
105 NSRange {
106 location: range.start as NSUInteger,
107 length: range.len() as NSUInteger,
108 }
109 }
110}
111
112unsafe impl objc::Encode for NSRange {
113 fn encode() -> objc::Encoding {
114 let encoding = format!(
115 "{{NSRange={}{}}}",
116 NSUInteger::encode().as_str(),
117 NSUInteger::encode().as_str()
118 );
119 unsafe { objc::Encoding::from_str(&encoding) }
120 }
121}
122
123unsafe fn ns_string(string: &str) -> id {
124 NSString::alloc(nil).init_str(string).autorelease()
125}
126
127impl From<NSSize> for Size<Pixels> {
128 fn from(value: NSSize) -> Self {
129 Size {
130 width: px(value.width as f32),
131 height: px(value.height as f32),
132 }
133 }
134}
135
136impl From<NSRect> for Size<Pixels> {
137 fn from(rect: NSRect) -> Self {
138 let NSSize { width, height } = rect.size;
139 size(width.into(), height.into())
140 }
141}
142
143impl From<NSRect> for Size<DevicePixels> {
144 fn from(rect: NSRect) -> Self {
145 let NSSize { width, height } = rect.size;
146 size(DevicePixels(width as i32), DevicePixels(height as i32))
147 }
148}