diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index d32da6580a..0803074503 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -263,7 +263,10 @@ pub struct SharedState { is_simple_fullscreen: bool, pub saved_style: Option, /// Presentation options saved before entering `set_simple_fullscreen`, and - /// restored upon exiting it + /// restored upon exiting it. Also used when transitioning from Borderless to + /// Exclusive fullscreen in `set_fullscreen` because we need to disable the menu + /// bar in exclusive fullscreen but want to restore the original options when + /// transitioning back to borderless fullscreen. save_presentation_opts: Option, pub saved_desktop_display_mode: Option<(CGDisplay, CGDisplayMode)>, } @@ -764,6 +767,14 @@ impl UnownedWindow { let mut fade_token = ffi::kCGDisplayFadeReservationInvalidToken; + unsafe { + let app = NSApp(); + trace!("Locked shared state in `set_fullscreen`"); + + let mut shared_state_lock = self.shared_state.lock().unwrap(); + shared_state_lock.save_presentation_opts = Some(app.presentationOptions_()); + } + unsafe { // Fade to black (and wait for the fade to complete) to hide the // flicker from capturing the display and switching display mode @@ -814,7 +825,6 @@ impl UnownedWindow { trace!("Locked shared state in `set_fullscreen`"); let mut shared_state_lock = self.shared_state.lock().unwrap(); shared_state_lock.fullscreen = fullscreen.clone(); - trace!("Unlocked shared state in `set_fullscreen`"); match (&old_fullscreen, &fullscreen) { (&None, &Some(_)) => unsafe { @@ -853,16 +863,33 @@ impl UnownedWindow { // of the menu bar, and this looks broken, so we must make sure // that the menu bar is disabled. This is done in the window // delegate in `window:willUseFullScreenPresentationOptions:`. + let app = NSApp(); + trace!("Locked shared state in `set_fullscreen`"); + shared_state_lock.save_presentation_opts = Some(app.presentationOptions_()); + + let presentation_options = + NSApplicationPresentationOptions::NSApplicationPresentationFullScreen + | NSApplicationPresentationOptions::NSApplicationPresentationHideDock + | NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar; + app.setPresentationOptions_(presentation_options); + let () = msg_send![*self.ns_window, setLevel: ffi::CGShieldingWindowLevel() + 1]; }, ( &Some(Fullscreen::Exclusive(RootVideoMode { ref video_mode })), &Some(Fullscreen::Borderless(_)), ) => unsafe { + let presentation_options = shared_state_lock.save_presentation_opts; + if presentation_options.is_some() { + let app = NSApp(); + app.setPresentationOptions_(presentation_options.unwrap()); + } + util::restore_display_mode_async(video_mode.monitor().inner.native_identifier()); }, _ => (), - } + }; + trace!("Unlocked shared state in `set_fullscreen`"); } #[inline] diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 7766893782..b57c4990e8 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -447,10 +447,10 @@ extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) { } extern "C" fn window_will_use_fullscreen_presentation_options( - _this: &Object, + this: &Object, _: Sel, _: id, - _proposed_options: NSUInteger, + proposed_options: NSUInteger, ) -> NSUInteger { // Generally, games will want to disable the menu bar and the dock. Ideally, // this would be configurable by the user. Unfortunately because of our @@ -460,10 +460,22 @@ extern "C" fn window_will_use_fullscreen_presentation_options( // still want to make this configurable for borderless fullscreen. Right now // we don't, for consistency. If we do, it should be documented that the // user-provided options are ignored in exclusive fullscreen. - (NSApplicationPresentationOptions::NSApplicationPresentationFullScreen - | NSApplicationPresentationOptions::NSApplicationPresentationHideDock - | NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar) - .bits() + let mut options: NSUInteger = proposed_options; + with_state(this, |state| { + state.with_window(|window| { + trace!("Locked shared state in `window_will_use_fullscreen_presentation_options`"); + let shared_state = window.shared_state.lock().unwrap(); + if let Some(Fullscreen::Exclusive(_)) = shared_state.fullscreen { + options = (NSApplicationPresentationOptions::NSApplicationPresentationFullScreen + | NSApplicationPresentationOptions::NSApplicationPresentationHideDock + | NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar) + .bits(); + } + trace!("Unlocked shared state in `window_will_use_fullscreen_presentation_options`"); + }) + }); + + options } /// Invoked when entered fullscreen