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 fn set_glass_opacity(&self, opacity: f64);
132}
133
134impl WindowExtMacOS for Window {
135 #[inline]
136 fn simple_fullscreen(&self) -> bool {
137 self.window.maybe_wait_on_main(|w| w.simple_fullscreen())
138 }
139
140 #[inline]
141 fn set_simple_fullscreen(&self, fullscreen: bool) -> bool {
142 self.window
143 .maybe_wait_on_main(move |w| w.set_simple_fullscreen(fullscreen))
144 }
145
146 #[inline]
147 fn has_shadow(&self) -> bool {
148 self.window.maybe_wait_on_main(|w| w.has_shadow())
149 }
150
151 #[inline]
152 fn set_has_shadow(&self, has_shadow: bool) {
153 self.window
154 .maybe_queue_on_main(move |w| w.set_has_shadow(has_shadow))
155 }
156
157 #[inline]
158 fn set_background_color(&self, r: f64, g: f64, b: f64, a: f64) {
159 self.window
160 .maybe_queue_on_main(move |w| w.set_background_color(r, g, b, a))
161 }
162
163 #[inline]
164 fn set_glass_opacity(&self, opacity: f64) {
165 self.window
166 .maybe_queue_on_main(move |w| w.set_glass_opacity(opacity))
167 }
168
169 #[inline]
170 fn set_tabbing_identifier(&self, identifier: &str) {
171 self.window
172 .maybe_wait_on_main(|w| w.set_tabbing_identifier(identifier))
173 }
174
175 #[inline]
176 fn tabbing_identifier(&self) -> String {
177 self.window.maybe_wait_on_main(|w| w.tabbing_identifier())
178 }
179
180 #[inline]
181 fn select_next_tab(&self) {
182 self.window.maybe_queue_on_main(|w| w.select_next_tab())
183 }
184
185 #[inline]
186 fn select_previous_tab(&self) {
187 self.window.maybe_queue_on_main(|w| w.select_previous_tab())
188 }
189
190 #[inline]
191 fn select_tab_at_index(&self, index: usize) {
192 self.window
193 .maybe_queue_on_main(move |w| w.select_tab_at_index(index))
194 }
195
196 #[inline]
197 fn num_tabs(&self) -> usize {
198 self.window.maybe_wait_on_main(|w| w.num_tabs())
199 }
200
201 #[inline]
202 fn is_document_edited(&self) -> bool {
203 self.window.maybe_wait_on_main(|w| w.is_document_edited())
204 }
205
206 #[inline]
207 fn set_document_edited(&self, edited: bool) {
208 self.window
209 .maybe_queue_on_main(move |w| w.set_document_edited(edited))
210 }
211
212 #[inline]
213 fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) {
214 self.window
215 .maybe_queue_on_main(move |w| w.set_option_as_alt(option_as_alt))
216 }
217
218 #[inline]
219 fn option_as_alt(&self) -> OptionAsAlt {
220 self.window.maybe_wait_on_main(|w| w.option_as_alt())
221 }
222
223 #[inline]
224 fn set_unified_titlebar(&self, unified_titlebar: bool) {
225 self.window
226 .maybe_wait_on_main(|w| w.set_unified_titlebar(unified_titlebar))
227 }
228
229 #[inline]
230 fn unified_titlebar(&self) -> bool {
231 self.window.maybe_wait_on_main(|w| w.unified_titlebar())
232 }
233
234 #[inline]
235 fn set_colorspace(&self, colorspace: Colorspace) {
236 self.window
237 .maybe_queue_on_main(move |w| w.set_colorspace(colorspace))
238 }
239
240 #[inline]
241 fn set_traffic_light_position(&self, position: Option<(f64, f64)>) {
242 self.window
243 .maybe_queue_on_main(move |w| w.set_traffic_light_position(position))
244 }
245}
246
247#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
249pub enum ActivationPolicy {
250 #[default]
252 Regular,
253
254 Accessory,
256
257 Prohibited,
259}
260
261pub trait WindowAttributesExtMacOS {
271 fn with_movable_by_window_background(
273 self,
274 movable_by_window_background: bool,
275 ) -> Self;
276 fn with_titlebar_transparent(self, titlebar_transparent: bool) -> Self;
278 fn with_title_hidden(self, title_hidden: bool) -> Self;
280 fn with_titlebar_hidden(self, titlebar_hidden: bool) -> Self;
282 fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> Self;
284 fn with_fullsize_content_view(self, fullsize_content_view: bool) -> Self;
286 fn with_disallow_hidpi(self, disallow_hidpi: bool) -> Self;
287 fn with_has_shadow(self, has_shadow: bool) -> Self;
288 fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> Self;
290 fn with_tabbing_identifier(self, identifier: &str) -> Self;
294 fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self;
298 fn with_unified_titlebar(self, unified_titlebar: bool) -> Self;
300 fn with_colorspace(self, colorspace: Colorspace) -> Self;
302 fn with_traffic_light_position(self, x: f64, y: f64) -> Self;
305}
306
307impl WindowAttributesExtMacOS for WindowAttributes {
308 #[inline]
309 fn with_movable_by_window_background(
310 mut self,
311 movable_by_window_background: bool,
312 ) -> Self {
313 self.platform_specific.movable_by_window_background =
314 movable_by_window_background;
315 self
316 }
317
318 #[inline]
319 fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self {
320 self.platform_specific.titlebar_transparent = titlebar_transparent;
321 self
322 }
323
324 #[inline]
325 fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self {
326 self.platform_specific.titlebar_hidden = titlebar_hidden;
327 self
328 }
329
330 #[inline]
331 fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self {
332 self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
333 self
334 }
335
336 #[inline]
337 fn with_title_hidden(mut self, title_hidden: bool) -> Self {
338 self.platform_specific.title_hidden = title_hidden;
339 self
340 }
341
342 #[inline]
343 fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self {
344 self.platform_specific.fullsize_content_view = fullsize_content_view;
345 self
346 }
347
348 #[inline]
349 fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self {
350 self.platform_specific.disallow_hidpi = disallow_hidpi;
351 self
352 }
353
354 #[inline]
355 fn with_has_shadow(mut self, has_shadow: bool) -> Self {
356 self.platform_specific.has_shadow = has_shadow;
357 self
358 }
359
360 #[inline]
361 fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self {
362 self.platform_specific.accepts_first_mouse = accepts_first_mouse;
363 self
364 }
365
366 #[inline]
367 fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self {
368 self.platform_specific
369 .tabbing_identifier
370 .replace(tabbing_identifier.to_string());
371 self
372 }
373
374 #[inline]
375 fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self {
376 self.platform_specific.option_as_alt = option_as_alt;
377 self
378 }
379
380 #[inline]
381 fn with_unified_titlebar(mut self, unified_titlebar: bool) -> Self {
382 self.platform_specific.unified_titlebar = unified_titlebar;
383 self
384 }
385
386 #[inline]
387 fn with_colorspace(mut self, colorspace: Colorspace) -> Self {
388 self.platform_specific.colorspace = Some(colorspace);
389 self
390 }
391
392 #[inline]
393 fn with_traffic_light_position(mut self, x: f64, y: f64) -> Self {
394 self.platform_specific.traffic_light_position = Some((x, y));
395 self
396 }
397}
398
399pub trait EventLoopBuilderExtMacOS {
400 fn with_activation_policy(
421 &mut self,
422 activation_policy: ActivationPolicy,
423 ) -> &mut Self;
424
425 fn with_default_menu(&mut self, enable: bool) -> &mut Self;
446
447 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self;
452}
453
454impl<T> EventLoopBuilderExtMacOS for EventLoopBuilder<T> {
455 #[inline]
456 fn with_activation_policy(
457 &mut self,
458 activation_policy: ActivationPolicy,
459 ) -> &mut Self {
460 self.platform_specific.activation_policy = activation_policy;
461 self
462 }
463
464 #[inline]
465 fn with_default_menu(&mut self, enable: bool) -> &mut Self {
466 self.platform_specific.default_menu = enable;
467 self
468 }
469
470 #[inline]
471 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self {
472 self.platform_specific.activate_ignoring_other_apps = ignore;
473 self
474 }
475}
476
477pub trait MonitorHandleExtMacOS {
479 fn native_id(&self) -> u32;
481 fn ns_screen(&self) -> Option<*mut c_void>;
483}
484
485impl MonitorHandleExtMacOS for MonitorHandle {
486 #[inline]
487 fn native_id(&self) -> u32 {
488 self.inner.native_identifier()
489 }
490
491 fn ns_screen(&self) -> Option<*mut c_void> {
492 let mtm = unsafe { objc2_foundation::MainThreadMarker::new_unchecked() };
494 self.inner
495 .ns_screen(mtm)
496 .map(|s| objc2::rc::Retained::as_ptr(&s) as _)
497 }
498}
499
500pub trait ActiveEventLoopExtMacOS {
502 fn hide_application(&self);
505 fn hide_other_applications(&self);
508 fn set_allows_automatic_window_tabbing(&self, enabled: bool);
512 fn allows_automatic_window_tabbing(&self) -> bool;
514}
515
516impl ActiveEventLoopExtMacOS for ActiveEventLoop {
517 fn hide_application(&self) {
518 self.p.hide_application()
519 }
520
521 fn hide_other_applications(&self) {
522 self.p.hide_other_applications()
523 }
524
525 fn set_allows_automatic_window_tabbing(&self, enabled: bool) {
526 self.p.set_allows_automatic_window_tabbing(enabled);
527 }
528
529 fn allows_automatic_window_tabbing(&self) -> bool {
530 self.p.allows_automatic_window_tabbing()
531 }
532}
533
534#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
538pub enum OptionAsAlt {
539 OnlyLeft,
541
542 OnlyRight,
544
545 Both,
547
548 #[default]
550 None,
551}