1use std::os::raw::c_void;
18
19#[cfg(feature = "serde")]
20use serde::{Deserialize, Serialize};
21
22use crate::event_loop::{ActiveEventLoop, EventLoopBuilder};
23use crate::monitor::MonitorHandle;
24use crate::window::{Window, WindowAttributes};
25
26pub trait WindowExtMacOS {
28 fn simple_fullscreen(&self) -> bool;
30
31 fn set_simple_fullscreen(&self, fullscreen: bool) -> bool;
39
40 fn has_shadow(&self) -> bool;
42
43 fn set_has_shadow(&self, has_shadow: bool);
45
46 fn set_tabbing_identifier(&self, identifier: &str);
50
51 fn tabbing_identifier(&self) -> String;
53
54 fn select_next_tab(&self);
56
57 fn select_previous_tab(&self);
59
60 fn select_tab_at_index(&self, index: usize);
64
65 fn num_tabs(&self) -> usize;
67
68 fn is_document_edited(&self) -> bool;
83
84 fn set_document_edited(&self, edited: bool);
86
87 fn set_option_as_alt(&self, option_as_alt: OptionAsAlt);
94
95 fn option_as_alt(&self) -> OptionAsAlt;
97
98 fn set_borderless_game(&self, borderless_game: bool);
100
101 fn is_borderless_game(&self) -> bool;
103}
104
105impl WindowExtMacOS for Window {
106 #[inline]
107 fn simple_fullscreen(&self) -> bool {
108 self.window.maybe_wait_on_main(|w| w.simple_fullscreen())
109 }
110
111 #[inline]
112 fn set_simple_fullscreen(&self, fullscreen: bool) -> bool {
113 self.window.maybe_wait_on_main(move |w| w.set_simple_fullscreen(fullscreen))
114 }
115
116 #[inline]
117 fn has_shadow(&self) -> bool {
118 self.window.maybe_wait_on_main(|w| w.has_shadow())
119 }
120
121 #[inline]
122 fn set_has_shadow(&self, has_shadow: bool) {
123 self.window.maybe_queue_on_main(move |w| w.set_has_shadow(has_shadow))
124 }
125
126 #[inline]
127 fn set_tabbing_identifier(&self, identifier: &str) {
128 self.window.maybe_wait_on_main(|w| w.set_tabbing_identifier(identifier))
129 }
130
131 #[inline]
132 fn tabbing_identifier(&self) -> String {
133 self.window.maybe_wait_on_main(|w| w.tabbing_identifier())
134 }
135
136 #[inline]
137 fn select_next_tab(&self) {
138 self.window.maybe_queue_on_main(|w| w.select_next_tab())
139 }
140
141 #[inline]
142 fn select_previous_tab(&self) {
143 self.window.maybe_queue_on_main(|w| w.select_previous_tab())
144 }
145
146 #[inline]
147 fn select_tab_at_index(&self, index: usize) {
148 self.window.maybe_queue_on_main(move |w| w.select_tab_at_index(index))
149 }
150
151 #[inline]
152 fn num_tabs(&self) -> usize {
153 self.window.maybe_wait_on_main(|w| w.num_tabs())
154 }
155
156 #[inline]
157 fn is_document_edited(&self) -> bool {
158 self.window.maybe_wait_on_main(|w| w.is_document_edited())
159 }
160
161 #[inline]
162 fn set_document_edited(&self, edited: bool) {
163 self.window.maybe_queue_on_main(move |w| w.set_document_edited(edited))
164 }
165
166 #[inline]
167 fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) {
168 self.window.maybe_queue_on_main(move |w| w.set_option_as_alt(option_as_alt))
169 }
170
171 #[inline]
172 fn option_as_alt(&self) -> OptionAsAlt {
173 self.window.maybe_wait_on_main(|w| w.option_as_alt())
174 }
175
176 #[inline]
177 fn set_borderless_game(&self, borderless_game: bool) {
178 self.window.maybe_wait_on_main(|w| w.set_borderless_game(borderless_game))
179 }
180
181 #[inline]
182 fn is_borderless_game(&self) -> bool {
183 self.window.maybe_wait_on_main(|w| w.is_borderless_game())
184 }
185}
186
187#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
189pub enum ActivationPolicy {
190 #[default]
192 Regular,
193
194 Accessory,
196
197 Prohibited,
199}
200
201pub trait WindowAttributesExtMacOS {
211 fn with_movable_by_window_background(self, movable_by_window_background: bool) -> Self;
213 fn with_titlebar_transparent(self, titlebar_transparent: bool) -> Self;
215 fn with_title_hidden(self, title_hidden: bool) -> Self;
217 fn with_titlebar_hidden(self, titlebar_hidden: bool) -> Self;
219 fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> Self;
221 fn with_fullsize_content_view(self, fullsize_content_view: bool) -> Self;
223 fn with_disallow_hidpi(self, disallow_hidpi: bool) -> Self;
224 fn with_has_shadow(self, has_shadow: bool) -> Self;
225 fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> Self;
227 fn with_tabbing_identifier(self, identifier: &str) -> Self;
231 fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self;
235 fn with_borderless_game(self, borderless_game: bool) -> Self;
237}
238
239impl WindowAttributesExtMacOS for WindowAttributes {
240 #[inline]
241 fn with_movable_by_window_background(mut self, movable_by_window_background: bool) -> Self {
242 self.platform_specific.movable_by_window_background = movable_by_window_background;
243 self
244 }
245
246 #[inline]
247 fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self {
248 self.platform_specific.titlebar_transparent = titlebar_transparent;
249 self
250 }
251
252 #[inline]
253 fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self {
254 self.platform_specific.titlebar_hidden = titlebar_hidden;
255 self
256 }
257
258 #[inline]
259 fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self {
260 self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden;
261 self
262 }
263
264 #[inline]
265 fn with_title_hidden(mut self, title_hidden: bool) -> Self {
266 self.platform_specific.title_hidden = title_hidden;
267 self
268 }
269
270 #[inline]
271 fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self {
272 self.platform_specific.fullsize_content_view = fullsize_content_view;
273 self
274 }
275
276 #[inline]
277 fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self {
278 self.platform_specific.disallow_hidpi = disallow_hidpi;
279 self
280 }
281
282 #[inline]
283 fn with_has_shadow(mut self, has_shadow: bool) -> Self {
284 self.platform_specific.has_shadow = has_shadow;
285 self
286 }
287
288 #[inline]
289 fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self {
290 self.platform_specific.accepts_first_mouse = accepts_first_mouse;
291 self
292 }
293
294 #[inline]
295 fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self {
296 self.platform_specific.tabbing_identifier.replace(tabbing_identifier.to_string());
297 self
298 }
299
300 #[inline]
301 fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self {
302 self.platform_specific.option_as_alt = option_as_alt;
303 self
304 }
305
306 #[inline]
307 fn with_borderless_game(mut self, borderless_game: bool) -> Self {
308 self.platform_specific.borderless_game = borderless_game;
309 self
310 }
311}
312
313pub trait EventLoopBuilderExtMacOS {
314 fn with_activation_policy(&mut self, activation_policy: ActivationPolicy) -> &mut Self;
338
339 fn with_default_menu(&mut self, enable: bool) -> &mut Self;
360
361 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self;
366}
367
368impl<T> EventLoopBuilderExtMacOS for EventLoopBuilder<T> {
369 #[inline]
370 fn with_activation_policy(&mut self, activation_policy: ActivationPolicy) -> &mut Self {
371 self.platform_specific.activation_policy = Some(activation_policy);
372 self
373 }
374
375 #[inline]
376 fn with_default_menu(&mut self, enable: bool) -> &mut Self {
377 self.platform_specific.default_menu = enable;
378 self
379 }
380
381 #[inline]
382 fn with_activate_ignoring_other_apps(&mut self, ignore: bool) -> &mut Self {
383 self.platform_specific.activate_ignoring_other_apps = ignore;
384 self
385 }
386}
387
388pub trait MonitorHandleExtMacOS {
390 fn native_id(&self) -> u32;
392 fn ns_screen(&self) -> Option<*mut c_void>;
394}
395
396impl MonitorHandleExtMacOS for MonitorHandle {
397 #[inline]
398 fn native_id(&self) -> u32 {
399 self.inner.native_identifier()
400 }
401
402 fn ns_screen(&self) -> Option<*mut c_void> {
403 let mtm = unsafe { objc2_foundation::MainThreadMarker::new_unchecked() };
405 self.inner.ns_screen(mtm).map(|s| objc2::rc::Retained::as_ptr(&s) as _)
406 }
407}
408
409pub trait ActiveEventLoopExtMacOS {
411 fn hide_application(&self);
414 fn hide_other_applications(&self);
417 fn set_allows_automatic_window_tabbing(&self, enabled: bool);
421 fn allows_automatic_window_tabbing(&self) -> bool;
423}
424
425impl ActiveEventLoopExtMacOS for ActiveEventLoop {
426 fn hide_application(&self) {
427 self.p.hide_application()
428 }
429
430 fn hide_other_applications(&self) {
431 self.p.hide_other_applications()
432 }
433
434 fn set_allows_automatic_window_tabbing(&self, enabled: bool) {
435 self.p.set_allows_automatic_window_tabbing(enabled);
436 }
437
438 fn allows_automatic_window_tabbing(&self) -> bool {
439 self.p.allows_automatic_window_tabbing()
440 }
441}
442
443#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
448pub enum OptionAsAlt {
449 OnlyLeft,
451
452 OnlyRight,
454
455 Both,
457
458 #[default]
460 None,
461}