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 fn with_mouse_down_can_move_window(self, can_move: bool) -> Self;
306}
307
308impl WindowAttributesExtMacOS for WindowAttributes {
309 #[inline]
310 fn with_movable_by_window_background(
311 mut self,
312 movable_by_window_background: bool,
313 ) -> Self {
314 self.platform_specific.movable_by_window_background =
315 movable_by_window_background;
316 self
317 }
318
319 #[inline]
320 fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self {
321 self.platform_specific.titlebar_transparent = titlebar_transparent;
322 self
323 }
324
325 #[inline]
326 fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self {
327 self.platform_specific.titlebar_hidden = titlebar_hidden;
328 self
329 }
330
331 #[inline]
332 fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self {
333 self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
334 self
335 }
336
337 #[inline]
338 fn with_title_hidden(mut self, title_hidden: bool) -> Self {
339 self.platform_specific.title_hidden = title_hidden;
340 self
341 }
342
343 #[inline]
344 fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self {
345 self.platform_specific.fullsize_content_view = fullsize_content_view;
346 self
347 }
348
349 #[inline]
350 fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self {
351 self.platform_specific.disallow_hidpi = disallow_hidpi;
352 self
353 }
354
355 #[inline]
356 fn with_has_shadow(mut self, has_shadow: bool) -> Self {
357 self.platform_specific.has_shadow = has_shadow;
358 self
359 }
360
361 #[inline]
362 fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self {
363 self.platform_specific.accepts_first_mouse = accepts_first_mouse;
364 self
365 }
366
367 #[inline]
368 fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self {
369 self.platform_specific
370 .tabbing_identifier
371 .replace(tabbing_identifier.to_string());
372 self
373 }
374
375 #[inline]
376 fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self {
377 self.platform_specific.option_as_alt = option_as_alt;
378 self
379 }
380
381 #[inline]
382 fn with_unified_titlebar(mut self, unified_titlebar: bool) -> Self {
383 self.platform_specific.unified_titlebar = unified_titlebar;
384 self
385 }
386
387 #[inline]
388 fn with_colorspace(mut self, colorspace: Colorspace) -> Self {
389 self.platform_specific.colorspace = Some(colorspace);
390 self
391 }
392
393 #[inline]
394 fn with_traffic_light_position(mut self, x: f64, y: f64) -> Self {
395 self.platform_specific.traffic_light_position = Some((x, y));
396 self
397 }
398
399 #[inline]
400 fn with_mouse_down_can_move_window(mut self, can_move: bool) -> Self {
401 self.platform_specific.mouse_down_can_move_window = can_move;
402 self
403 }
404}
405
406pub trait EventLoopBuilderExtMacOS {
407 fn with_activation_policy(
428 &mut self,
429 activation_policy: ActivationPolicy,
430 ) -> &mut Self;
431
432 fn with_default_menu(&mut self, enable: bool) -> &mut Self;
453
454 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self;
459}
460
461impl<T> EventLoopBuilderExtMacOS for EventLoopBuilder<T> {
462 #[inline]
463 fn with_activation_policy(
464 &mut self,
465 activation_policy: ActivationPolicy,
466 ) -> &mut Self {
467 self.platform_specific.activation_policy = activation_policy;
468 self
469 }
470
471 #[inline]
472 fn with_default_menu(&mut self, enable: bool) -> &mut Self {
473 self.platform_specific.default_menu = enable;
474 self
475 }
476
477 #[inline]
478 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self {
479 self.platform_specific.activate_ignoring_other_apps = ignore;
480 self
481 }
482}
483
484pub trait MonitorHandleExtMacOS {
486 fn native_id(&self) -> u32;
488 fn ns_screen(&self) -> Option<*mut c_void>;
490}
491
492impl MonitorHandleExtMacOS for MonitorHandle {
493 #[inline]
494 fn native_id(&self) -> u32 {
495 self.inner.native_identifier()
496 }
497
498 fn ns_screen(&self) -> Option<*mut c_void> {
499 let mtm = unsafe { objc2_foundation::MainThreadMarker::new_unchecked() };
501 self.inner
502 .ns_screen(mtm)
503 .map(|s| objc2::rc::Retained::as_ptr(&s) as _)
504 }
505}
506
507pub trait ActiveEventLoopExtMacOS {
509 fn hide_application(&self);
512 fn hide_other_applications(&self);
515 fn set_allows_automatic_window_tabbing(&self, enabled: bool);
519 fn allows_automatic_window_tabbing(&self) -> bool;
521}
522
523impl ActiveEventLoopExtMacOS for ActiveEventLoop {
524 fn hide_application(&self) {
525 self.p.hide_application()
526 }
527
528 fn hide_other_applications(&self) {
529 self.p.hide_other_applications()
530 }
531
532 fn set_allows_automatic_window_tabbing(&self, enabled: bool) {
533 self.p.set_allows_automatic_window_tabbing(enabled);
534 }
535
536 fn allows_automatic_window_tabbing(&self) -> bool {
537 self.p.allows_automatic_window_tabbing()
538 }
539}
540
541#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
545pub enum OptionAsAlt {
546 OnlyLeft,
548
549 OnlyRight,
551
552 Both,
554
555 #[default]
557 None,
558}