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 fn set_traffic_light_position(&self, position: Option<(f64, f64)>);
122}
123
124impl WindowExtMacOS for Window {
125 #[inline]
126 fn simple_fullscreen(&self) -> bool {
127 self.window.maybe_wait_on_main(|w| w.simple_fullscreen())
128 }
129
130 #[inline]
131 fn set_simple_fullscreen(&self, fullscreen: bool) -> bool {
132 self.window
133 .maybe_wait_on_main(move |w| w.set_simple_fullscreen(fullscreen))
134 }
135
136 #[inline]
137 fn has_shadow(&self) -> bool {
138 self.window.maybe_wait_on_main(|w| w.has_shadow())
139 }
140
141 #[inline]
142 fn set_has_shadow(&self, has_shadow: bool) {
143 self.window
144 .maybe_queue_on_main(move |w| w.set_has_shadow(has_shadow))
145 }
146
147 #[inline]
148 fn set_background_color(&self, r: f64, g: f64, b: f64, a: f64) {
149 self.window
150 .maybe_queue_on_main(move |w| w.set_background_color(r, g, b, a))
151 }
152
153 #[inline]
154 fn set_tabbing_identifier(&self, identifier: &str) {
155 self.window
156 .maybe_wait_on_main(|w| w.set_tabbing_identifier(identifier))
157 }
158
159 #[inline]
160 fn tabbing_identifier(&self) -> String {
161 self.window.maybe_wait_on_main(|w| w.tabbing_identifier())
162 }
163
164 #[inline]
165 fn select_next_tab(&self) {
166 self.window.maybe_queue_on_main(|w| w.select_next_tab())
167 }
168
169 #[inline]
170 fn select_previous_tab(&self) {
171 self.window.maybe_queue_on_main(|w| w.select_previous_tab())
172 }
173
174 #[inline]
175 fn select_tab_at_index(&self, index: usize) {
176 self.window
177 .maybe_queue_on_main(move |w| w.select_tab_at_index(index))
178 }
179
180 #[inline]
181 fn num_tabs(&self) -> usize {
182 self.window.maybe_wait_on_main(|w| w.num_tabs())
183 }
184
185 #[inline]
186 fn is_document_edited(&self) -> bool {
187 self.window.maybe_wait_on_main(|w| w.is_document_edited())
188 }
189
190 #[inline]
191 fn set_document_edited(&self, edited: bool) {
192 self.window
193 .maybe_queue_on_main(move |w| w.set_document_edited(edited))
194 }
195
196 #[inline]
197 fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) {
198 self.window
199 .maybe_queue_on_main(move |w| w.set_option_as_alt(option_as_alt))
200 }
201
202 #[inline]
203 fn option_as_alt(&self) -> OptionAsAlt {
204 self.window.maybe_wait_on_main(|w| w.option_as_alt())
205 }
206
207 #[inline]
208 fn set_unified_titlebar(&self, unified_titlebar: bool) {
209 self.window
210 .maybe_wait_on_main(|w| w.set_unified_titlebar(unified_titlebar))
211 }
212
213 #[inline]
214 fn unified_titlebar(&self) -> bool {
215 self.window.maybe_wait_on_main(|w| w.unified_titlebar())
216 }
217
218 #[inline]
219 fn set_colorspace(&self, colorspace: Colorspace) {
220 self.window
221 .maybe_queue_on_main(move |w| w.set_colorspace(colorspace))
222 }
223
224 #[inline]
225 fn set_traffic_light_position(&self, position: Option<(f64, f64)>) {
226 self.window
227 .maybe_queue_on_main(move |w| w.set_traffic_light_position(position))
228 }
229}
230
231#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
233pub enum ActivationPolicy {
234 #[default]
236 Regular,
237
238 Accessory,
240
241 Prohibited,
243}
244
245pub trait WindowAttributesExtMacOS {
255 fn with_movable_by_window_background(
257 self,
258 movable_by_window_background: bool,
259 ) -> Self;
260 fn with_titlebar_transparent(self, titlebar_transparent: bool) -> Self;
262 fn with_title_hidden(self, title_hidden: bool) -> Self;
264 fn with_titlebar_hidden(self, titlebar_hidden: bool) -> Self;
266 fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> Self;
268 fn with_fullsize_content_view(self, fullsize_content_view: bool) -> Self;
270 fn with_disallow_hidpi(self, disallow_hidpi: bool) -> Self;
271 fn with_has_shadow(self, has_shadow: bool) -> Self;
272 fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> Self;
274 fn with_tabbing_identifier(self, identifier: &str) -> Self;
278 fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self;
282 fn with_unified_titlebar(self, unified_titlebar: bool) -> Self;
284 fn with_colorspace(self, colorspace: Colorspace) -> Self;
286 fn with_traffic_light_position(self, x: f64, y: f64) -> Self;
289}
290
291impl WindowAttributesExtMacOS for WindowAttributes {
292 #[inline]
293 fn with_movable_by_window_background(
294 mut self,
295 movable_by_window_background: bool,
296 ) -> Self {
297 self.platform_specific.movable_by_window_background =
298 movable_by_window_background;
299 self
300 }
301
302 #[inline]
303 fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self {
304 self.platform_specific.titlebar_transparent = titlebar_transparent;
305 self
306 }
307
308 #[inline]
309 fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self {
310 self.platform_specific.titlebar_hidden = titlebar_hidden;
311 self
312 }
313
314 #[inline]
315 fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self {
316 self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
317 self
318 }
319
320 #[inline]
321 fn with_title_hidden(mut self, title_hidden: bool) -> Self {
322 self.platform_specific.title_hidden = title_hidden;
323 self
324 }
325
326 #[inline]
327 fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self {
328 self.platform_specific.fullsize_content_view = fullsize_content_view;
329 self
330 }
331
332 #[inline]
333 fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self {
334 self.platform_specific.disallow_hidpi = disallow_hidpi;
335 self
336 }
337
338 #[inline]
339 fn with_has_shadow(mut self, has_shadow: bool) -> Self {
340 self.platform_specific.has_shadow = has_shadow;
341 self
342 }
343
344 #[inline]
345 fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self {
346 self.platform_specific.accepts_first_mouse = accepts_first_mouse;
347 self
348 }
349
350 #[inline]
351 fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self {
352 self.platform_specific
353 .tabbing_identifier
354 .replace(tabbing_identifier.to_string());
355 self
356 }
357
358 #[inline]
359 fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self {
360 self.platform_specific.option_as_alt = option_as_alt;
361 self
362 }
363
364 #[inline]
365 fn with_unified_titlebar(mut self, unified_titlebar: bool) -> Self {
366 self.platform_specific.unified_titlebar = unified_titlebar;
367 self
368 }
369
370 #[inline]
371 fn with_colorspace(mut self, colorspace: Colorspace) -> Self {
372 self.platform_specific.colorspace = Some(colorspace);
373 self
374 }
375
376 #[inline]
377 fn with_traffic_light_position(mut self, x: f64, y: f64) -> Self {
378 self.platform_specific.traffic_light_position = Some((x, y));
379 self
380 }
381}
382
383pub trait EventLoopBuilderExtMacOS {
384 fn with_activation_policy(
405 &mut self,
406 activation_policy: ActivationPolicy,
407 ) -> &mut Self;
408
409 fn with_default_menu(&mut self, enable: bool) -> &mut Self;
430
431 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self;
436}
437
438impl<T> EventLoopBuilderExtMacOS for EventLoopBuilder<T> {
439 #[inline]
440 fn with_activation_policy(
441 &mut self,
442 activation_policy: ActivationPolicy,
443 ) -> &mut Self {
444 self.platform_specific.activation_policy = activation_policy;
445 self
446 }
447
448 #[inline]
449 fn with_default_menu(&mut self, enable: bool) -> &mut Self {
450 self.platform_specific.default_menu = enable;
451 self
452 }
453
454 #[inline]
455 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self {
456 self.platform_specific.activate_ignoring_other_apps = ignore;
457 self
458 }
459}
460
461pub trait MonitorHandleExtMacOS {
463 fn native_id(&self) -> u32;
465 fn ns_screen(&self) -> Option<*mut c_void>;
467}
468
469impl MonitorHandleExtMacOS for MonitorHandle {
470 #[inline]
471 fn native_id(&self) -> u32 {
472 self.inner.native_identifier()
473 }
474
475 fn ns_screen(&self) -> Option<*mut c_void> {
476 let mtm = unsafe { objc2_foundation::MainThreadMarker::new_unchecked() };
478 self.inner
479 .ns_screen(mtm)
480 .map(|s| objc2::rc::Retained::as_ptr(&s) as _)
481 }
482}
483
484pub trait ActiveEventLoopExtMacOS {
486 fn hide_application(&self);
489 fn hide_other_applications(&self);
492 fn set_allows_automatic_window_tabbing(&self, enabled: bool);
496 fn allows_automatic_window_tabbing(&self) -> bool;
498}
499
500impl ActiveEventLoopExtMacOS for ActiveEventLoop {
501 fn hide_application(&self) {
502 self.p.hide_application()
503 }
504
505 fn hide_other_applications(&self) {
506 self.p.hide_other_applications()
507 }
508
509 fn set_allows_automatic_window_tabbing(&self, enabled: bool) {
510 self.p.set_allows_automatic_window_tabbing(enabled);
511 }
512
513 fn allows_automatic_window_tabbing(&self) -> bool {
514 self.p.allows_automatic_window_tabbing()
515 }
516}
517
518#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
522pub enum OptionAsAlt {
523 OnlyLeft,
525
526 OnlyRight,
528
529 Both,
531
532 #[default]
534 None,
535}