Skip to content

Commit 5a6cfc3

Browse files
authored
Macos fullscreen & dialog support with run_return (#1581)
* Fix for fullscreen with run_return on mac * Cleanup * Removed a comment * fmt * This doesn't break exiting run_return anymore * Now you can also transition from code * Fmt & cleanup * Now using a atomic instead of a static bool * reinserted a line * Fmt * Added support for dialogs and child windows * Cargo fmt * Dialogs are now being shutdown properly * Cargo fmt * Update CHANGELOG.md
1 parent a4121a2 commit 5a6cfc3

File tree

4 files changed

+60
-20
lines changed

4 files changed

+60
-20
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- On Wayland, fix deadlock when calling to `set_inner_size` from a callback.
66
- On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`.
7+
- On MacOS, Fixed fullscreen and dialog support for `run_return`.
78

89
# 0.22.2 (2020-05-16)
910

src/platform_impl/macos/app_state.rs

+43-18
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ impl<T> EventHandler for EventLoopHandler<T> {
9292
struct Handler {
9393
ready: AtomicBool,
9494
in_callback: AtomicBool,
95+
dialog_is_closing: AtomicBool,
9596
control_flow: Mutex<ControlFlow>,
9697
control_flow_prev: Mutex<ControlFlow>,
9798
start_time: Mutex<Option<Instant>>,
@@ -223,6 +224,8 @@ impl Handler {
223224
}
224225
}
225226

227+
pub static INTERRUPT_EVENT_LOOP_EXIT: AtomicBool = AtomicBool::new(false);
228+
226229
pub enum AppState {}
227230

228231
impl AppState {
@@ -336,29 +339,51 @@ impl AppState {
336339
}
337340
if HANDLER.should_exit() {
338341
unsafe {
339-
let _: () = msg_send![NSApp(), stop: nil];
340-
341-
let pool = NSAutoreleasePool::new(nil);
342-
343-
let windows: id = msg_send![NSApp(), windows];
342+
let app: id = NSApp();
343+
let windows: id = msg_send![app, windows];
344344
let window: id = msg_send![windows, objectAtIndex:0];
345+
let window_count: usize = msg_send![windows, count];
345346
assert_ne!(window, nil);
346347

347-
let dummy_event: id = msg_send![class!(NSEvent),
348-
otherEventWithType: NSApplicationDefined
349-
location: NSPoint::new(0.0, 0.0)
350-
modifierFlags: 0
351-
timestamp: 0
352-
windowNumber: 0
353-
context: nil
354-
subtype: 0
355-
data1: 0
356-
data2: 0
357-
];
358-
// To stop event loop immediately, we need to post some event here.
359-
let _: () = msg_send![window, postEvent: dummy_event atStart: YES];
348+
let dialog_open = if window_count > 1 {
349+
let dialog: id = msg_send![windows, lastObject];
350+
let is_main_window: bool = msg_send![dialog, isMainWindow];
351+
msg_send![dialog, isVisible] && !is_main_window
352+
} else {
353+
false
354+
};
360355

356+
let dialog_is_closing = HANDLER.dialog_is_closing.load(Ordering::SeqCst);
357+
let pool = NSAutoreleasePool::new(nil);
358+
if !INTERRUPT_EVENT_LOOP_EXIT.load(Ordering::SeqCst)
359+
&& !dialog_open
360+
&& !dialog_is_closing
361+
{
362+
let _: () = msg_send![app, stop: nil];
363+
364+
let dummy_event: id = msg_send![class!(NSEvent),
365+
otherEventWithType: NSApplicationDefined
366+
location: NSPoint::new(0.0, 0.0)
367+
modifierFlags: 0
368+
timestamp: 0
369+
windowNumber: 0
370+
context: nil
371+
subtype: 0
372+
data1: 0
373+
data2: 0
374+
];
375+
// To stop event loop immediately, we need to post some event here.
376+
let _: () = msg_send![window, postEvent: dummy_event atStart: YES];
377+
}
361378
pool.drain();
379+
380+
let window_has_focus = msg_send![window, isKeyWindow];
381+
if !dialog_open && window_has_focus && dialog_is_closing {
382+
HANDLER.dialog_is_closing.store(false, Ordering::SeqCst);
383+
}
384+
if dialog_open {
385+
HANDLER.dialog_is_closing.store(true, Ordering::SeqCst);
386+
}
362387
};
363388
}
364389
HANDLER.update_start_time();

src/platform_impl/macos/window.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{
1919
platform::macos::{ActivationPolicy, RequestUserAttentionType, WindowExtMacOS},
2020
platform_impl::platform::{
2121
app_state::AppState,
22+
app_state::INTERRUPT_EVENT_LOOP_EXIT,
2223
ffi,
2324
monitor::{self, MonitorHandle, VideoMode},
2425
util::{self, IdRef},
@@ -820,6 +821,8 @@ impl UnownedWindow {
820821
shared_state_lock.fullscreen = fullscreen.clone();
821822
trace!("Unlocked shared state in `set_fullscreen`");
822823

824+
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
825+
823826
match (&old_fullscreen, &fullscreen) {
824827
(&None, &Some(_)) => unsafe {
825828
util::toggle_full_screen_async(
@@ -865,7 +868,7 @@ impl UnownedWindow {
865868
) => unsafe {
866869
util::restore_display_mode_async(video_mode.monitor().inner.native_identifier());
867870
},
868-
_ => (),
871+
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
869872
}
870873
}
871874

src/platform_impl/macos/window_delegate.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
f64,
33
os::raw::c_void,
4-
sync::{Arc, Weak},
4+
sync::{atomic::Ordering, Arc, Weak},
55
};
66

77
use cocoa::{
@@ -19,6 +19,7 @@ use crate::{
1919
event::{Event, ModifiersState, WindowEvent},
2020
platform_impl::platform::{
2121
app_state::AppState,
22+
app_state::INTERRUPT_EVENT_LOOP_EXIT,
2223
event::{EventProxy, EventWrapper},
2324
util::{self, IdRef},
2425
view::ViewState,
@@ -429,6 +430,9 @@ extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
429430
/// Invoked when before enter fullscreen
430431
extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
431432
trace!("Triggered `windowWillEnterFullscreen:`");
433+
434+
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
435+
432436
with_state(this, |state| {
433437
state.with_window(|window| {
434438
trace!("Locked shared state in `window_will_enter_fullscreen`");
@@ -459,6 +463,9 @@ extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
459463
/// Invoked when before exit fullscreen
460464
extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
461465
trace!("Triggered `windowWillExitFullScreen:`");
466+
467+
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
468+
462469
with_state(this, |state| {
463470
state.with_window(|window| {
464471
trace!("Locked shared state in `window_will_exit_fullscreen`");
@@ -492,6 +499,8 @@ extern "C" fn window_will_use_fullscreen_presentation_options(
492499

493500
/// Invoked when entered fullscreen
494501
extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
502+
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
503+
495504
trace!("Triggered `windowDidEnterFullscreen:`");
496505
with_state(this, |state| {
497506
state.initial_fullscreen = false;
@@ -512,6 +521,8 @@ extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
512521

513522
/// Invoked when exited fullscreen
514523
extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
524+
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
525+
515526
trace!("Triggered `windowDidExitFullscreen:`");
516527
with_state(this, |state| {
517528
state.with_window(|window| {

0 commit comments

Comments
 (0)