1use std::os::raw::c_void;
18
19use crate::event_loop::{ActiveEventLoop, EventLoopBuilder};
20use crate::monitor::MonitorHandle;
21use crate::window::{Window, WindowAttributes};
22
23#[derive(Clone, Copy, Debug, PartialEq)]
25pub enum Colorspace {
26 Srgb,
28 DisplayP3,
30 Rec2020,
32}
33
34pub trait WindowExtMacOS {
36 fn simple_fullscreen(&self) -> bool;
38
39 fn set_simple_fullscreen(&self, fullscreen: bool) -> bool;
47
48 fn has_shadow(&self) -> bool;
50
51 fn set_has_shadow(&self, has_shadow: bool);
53
54 fn set_background_color(&self, _r: f64, _g: f64, _b: f64, _a: f64);
56
57 fn set_tabbing_identifier(&self, identifier: &str);
61
62 fn tabbing_identifier(&self) -> String;
64
65 fn select_next_tab(&self);
67
68 fn select_previous_tab(&self);
70
71 fn select_tab_at_index(&self, index: usize);
75
76 fn num_tabs(&self) -> usize;
78
79 fn is_document_edited(&self) -> bool;
94
95 fn set_document_edited(&self, edited: bool);
97
98 fn set_option_as_alt(&self, option_as_alt: OptionAsAlt);
105
106 fn option_as_alt(&self) -> OptionAsAlt;
108
109 fn set_unified_titlebar(&self, unified_titlebar: bool);
112 fn unified_titlebar(&self) -> bool;
114
115 fn set_colorspace(&self, colorspace: Colorspace);
117}
118
119impl WindowExtMacOS for Window {
120 #[inline]
121 fn simple_fullscreen(&self) -> bool {
122 self.window.maybe_wait_on_main(|w| w.simple_fullscreen())
123 }
124
125 #[inline]
126 fn set_simple_fullscreen(&self, fullscreen: bool) -> bool {
127 self.window
128 .maybe_wait_on_main(move |w| w.set_simple_fullscreen(fullscreen))
129 }
130
131 #[inline]
132 fn has_shadow(&self) -> bool {
133 self.window.maybe_wait_on_main(|w| w.has_shadow())
134 }
135
136 #[inline]
137 fn set_has_shadow(&self, has_shadow: bool) {
138 self.window
139 .maybe_queue_on_main(move |w| w.set_has_shadow(has_shadow))
140 }
141
142 #[inline]
143 fn set_background_color(&self, r: f64, g: f64, b: f64, a: f64) {
144 self.window
145 .maybe_queue_on_main(move |w| w.set_background_color(r, g, b, a))
146 }
147
148 #[inline]
149 fn set_tabbing_identifier(&self, identifier: &str) {
150 self.window
151 .maybe_wait_on_main(|w| w.set_tabbing_identifier(identifier))
152 }
153
154 #[inline]
155 fn tabbing_identifier(&self) -> String {
156 self.window.maybe_wait_on_main(|w| w.tabbing_identifier())
157 }
158
159 #[inline]
160 fn select_next_tab(&self) {
161 self.window.maybe_queue_on_main(|w| w.select_next_tab())
162 }
163
164 #[inline]
165 fn select_previous_tab(&self) {
166 self.window.maybe_queue_on_main(|w| w.select_previous_tab())
167 }
168
169 #[inline]
170 fn select_tab_at_index(&self, index: usize) {
171 self.window
172 .maybe_queue_on_main(move |w| w.select_tab_at_index(index))
173 }
174
175 #[inline]
176 fn num_tabs(&self) -> usize {
177 self.window.maybe_wait_on_main(|w| w.num_tabs())
178 }
179
180 #[inline]
181 fn is_document_edited(&self) -> bool {
182 self.window.maybe_wait_on_main(|w| w.is_document_edited())
183 }
184
185 #[inline]
186 fn set_document_edited(&self, edited: bool) {
187 self.window
188 .maybe_queue_on_main(move |w| w.set_document_edited(edited))
189 }
190
191 #[inline]
192 fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) {
193 self.window
194 .maybe_queue_on_main(move |w| w.set_option_as_alt(option_as_alt))
195 }
196
197 #[inline]
198 fn option_as_alt(&self) -> OptionAsAlt {
199 self.window.maybe_wait_on_main(|w| w.option_as_alt())
200 }
201
202 #[inline]
203 fn set_unified_titlebar(&self, unified_titlebar: bool) {
204 self.window
205 .maybe_wait_on_main(|w| w.set_unified_titlebar(unified_titlebar))
206 }
207
208 #[inline]
209 fn unified_titlebar(&self) -> bool {
210 self.window.maybe_wait_on_main(|w| w.unified_titlebar())
211 }
212
213 #[inline]
214 fn set_colorspace(&self, colorspace: Colorspace) {
215 self.window
216 .maybe_queue_on_main(move |w| w.set_colorspace(colorspace))
217 }
218}
219
220#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
222pub enum ActivationPolicy {
223 #[default]
225 Regular,
226
227 Accessory,
229
230 Prohibited,
232}
233
234pub trait WindowAttributesExtMacOS {
244 fn with_movable_by_window_background(
246 self,
247 movable_by_window_background: bool,
248 ) -> Self;
249 fn with_titlebar_transparent(self, titlebar_transparent: bool) -> Self;
251 fn with_title_hidden(self, title_hidden: bool) -> Self;
253 fn with_titlebar_hidden(self, titlebar_hidden: bool) -> Self;
255 fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> Self;
257 fn with_fullsize_content_view(self, fullsize_content_view: bool) -> Self;
259 fn with_disallow_hidpi(self, disallow_hidpi: bool) -> Self;
260 fn with_has_shadow(self, has_shadow: bool) -> Self;
261 fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> Self;
263 fn with_tabbing_identifier(self, identifier: &str) -> Self;
267 fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self;
271 fn with_unified_titlebar(self, unified_titlebar: bool) -> Self;
273 fn with_colorspace(self, colorspace: Colorspace) -> Self;
275}
276
277impl WindowAttributesExtMacOS for WindowAttributes {
278 #[inline]
279 fn with_movable_by_window_background(
280 mut self,
281 movable_by_window_background: bool,
282 ) -> Self {
283 self.platform_specific.movable_by_window_background =
284 movable_by_window_background;
285 self
286 }
287
288 #[inline]
289 fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self {
290 self.platform_specific.titlebar_transparent = titlebar_transparent;
291 self
292 }
293
294 #[inline]
295 fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self {
296 self.platform_specific.titlebar_hidden = titlebar_hidden;
297 self
298 }
299
300 #[inline]
301 fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self {
302 self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
303 self
304 }
305
306 #[inline]
307 fn with_title_hidden(mut self, title_hidden: bool) -> Self {
308 self.platform_specific.title_hidden = title_hidden;
309 self
310 }
311
312 #[inline]
313 fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self {
314 self.platform_specific.fullsize_content_view = fullsize_content_view;
315 self
316 }
317
318 #[inline]
319 fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self {
320 self.platform_specific.disallow_hidpi = disallow_hidpi;
321 self
322 }
323
324 #[inline]
325 fn with_has_shadow(mut self, has_shadow: bool) -> Self {
326 self.platform_specific.has_shadow = has_shadow;
327 self
328 }
329
330 #[inline]
331 fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self {
332 self.platform_specific.accepts_first_mouse = accepts_first_mouse;
333 self
334 }
335
336 #[inline]
337 fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self {
338 self.platform_specific
339 .tabbing_identifier
340 .replace(tabbing_identifier.to_string());
341 self
342 }
343
344 #[inline]
345 fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self {
346 self.platform_specific.option_as_alt = option_as_alt;
347 self
348 }
349
350 #[inline]
351 fn with_unified_titlebar(mut self, unified_titlebar: bool) -> Self {
352 self.platform_specific.unified_titlebar = unified_titlebar;
353 self
354 }
355
356 #[inline]
357 fn with_colorspace(mut self, colorspace: Colorspace) -> Self {
358 self.platform_specific.colorspace = Some(colorspace);
359 self
360 }
361}
362
363pub trait EventLoopBuilderExtMacOS {
364 fn with_activation_policy(
385 &mut self,
386 activation_policy: ActivationPolicy,
387 ) -> &mut Self;
388
389 fn with_default_menu(&mut self, enable: bool) -> &mut Self;
410
411 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self;
416}
417
418impl<T> EventLoopBuilderExtMacOS for EventLoopBuilder<T> {
419 #[inline]
420 fn with_activation_policy(
421 &mut self,
422 activation_policy: ActivationPolicy,
423 ) -> &mut Self {
424 self.platform_specific.activation_policy = activation_policy;
425 self
426 }
427
428 #[inline]
429 fn with_default_menu(&mut self, enable: bool) -> &mut Self {
430 self.platform_specific.default_menu = enable;
431 self
432 }
433
434 #[inline]
435 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self {
436 self.platform_specific.activate_ignoring_other_apps = ignore;
437 self
438 }
439}
440
441pub trait MonitorHandleExtMacOS {
443 fn native_id(&self) -> u32;
445 fn ns_screen(&self) -> Option<*mut c_void>;
447}
448
449impl MonitorHandleExtMacOS for MonitorHandle {
450 #[inline]
451 fn native_id(&self) -> u32 {
452 self.inner.native_identifier()
453 }
454
455 fn ns_screen(&self) -> Option<*mut c_void> {
456 let mtm = unsafe { objc2_foundation::MainThreadMarker::new_unchecked() };
458 self.inner
459 .ns_screen(mtm)
460 .map(|s| objc2::rc::Retained::as_ptr(&s) as _)
461 }
462}
463
464pub trait ActiveEventLoopExtMacOS {
466 fn hide_application(&self);
469 fn hide_other_applications(&self);
472 fn set_allows_automatic_window_tabbing(&self, enabled: bool);
476 fn allows_automatic_window_tabbing(&self) -> bool;
478}
479
480impl ActiveEventLoopExtMacOS for ActiveEventLoop {
481 fn hide_application(&self) {
482 self.p.hide_application()
483 }
484
485 fn hide_other_applications(&self) {
486 self.p.hide_other_applications()
487 }
488
489 fn set_allows_automatic_window_tabbing(&self, enabled: bool) {
490 self.p.set_allows_automatic_window_tabbing(enabled);
491 }
492
493 fn allows_automatic_window_tabbing(&self) -> bool {
494 self.p.allows_automatic_window_tabbing()
495 }
496}
497
498#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
502pub enum OptionAsAlt {
503 OnlyLeft,
505
506 OnlyRight,
508
509 Both,
511
512 #[default]
514 None,
515}