mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
Show the menu bar in borderless fullscreen on macOS (#2053)
* In MacOS, only disable menu bar in exclusive fullscreen * Save and restore fullscreen options in set_fullscreen * Don't always cache presentation options when entering exclusive fullscreen This commit caches presentation options when entering exclusive fullscreen only if we're coming from borderless fullscreen. Then, when transitioning from exclusive -> borderless, if no cached presentation options are present, then the default borderless options are applied. This fixes the menu bar being unavailable when taking the following path: [not fullscreen] -> [exclusive fullscreen] -> [borderless fullscreen]. Without this commit, the presentation options from [not fullscreen] were being cached and then applied to [borderless fullscreen]. * Restore the window level when switching to exclusive fullscreen The hack of using `CGShieldingWindowLevel() + 1` in borderless fullscreen needs to be undone when switching from [borderless] -> [exclusive] fullscreen, otherwise there are menu bar glitches when following a path through [borderless] -> [exclusive] -> [borderless] modes. Now, this might appear to conflict with the 'always on top' feature which uses the 'floating window' level, but this feature appears to be broken anyway when entering and exiting fullscreen with an always-on-top window. So, rather than introducing logic to attempt to restore to the 'floating' level here, I think it's better to do the simple thing for now and then introduce logic for always-on-top windows when fixing the overall fullscreen behaviour. * Update the changelog Co-authored-by: Ehden Sinai <ehdens@gmail.com> Co-authored-by: Francesca Lovebloom <francesca@brainiumstudios.com>
This commit is contained in:
parent
3ecbea3c39
commit
f2de8475fc
|
@ -22,6 +22,7 @@
|
||||||
- On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`.
|
- On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`.
|
||||||
- On macOS, fix native file dialogs hanging the event loop.
|
- On macOS, fix native file dialogs hanging the event loop.
|
||||||
- On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland`
|
- On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland`
|
||||||
|
- On macOS, fix an issue that prevented the menu bar from showing in borderless fullscreen mode.
|
||||||
|
|
||||||
# 0.25.0 (2021-05-15)
|
# 0.25.0 (2021-05-15)
|
||||||
|
|
||||||
|
|
|
@ -281,7 +281,10 @@ pub struct SharedState {
|
||||||
is_simple_fullscreen: bool,
|
is_simple_fullscreen: bool,
|
||||||
pub saved_style: Option<NSWindowStyleMask>,
|
pub saved_style: Option<NSWindowStyleMask>,
|
||||||
/// Presentation options saved before entering `set_simple_fullscreen`, and
|
/// 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<NSApplicationPresentationOptions>,
|
save_presentation_opts: Option<NSApplicationPresentationOptions>,
|
||||||
pub saved_desktop_display_mode: Option<(CGDisplay, CGDisplayMode)>,
|
pub saved_desktop_display_mode: Option<(CGDisplay, CGDisplayMode)>,
|
||||||
}
|
}
|
||||||
|
@ -782,6 +785,15 @@ impl UnownedWindow {
|
||||||
|
|
||||||
let mut fade_token = ffi::kCGDisplayFadeReservationInvalidToken;
|
let mut fade_token = ffi::kCGDisplayFadeReservationInvalidToken;
|
||||||
|
|
||||||
|
if matches!(old_fullscreen, Some(Fullscreen::Borderless(_))) {
|
||||||
|
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 {
|
unsafe {
|
||||||
// Fade to black (and wait for the fade to complete) to hide the
|
// Fade to black (and wait for the fade to complete) to hide the
|
||||||
// flicker from capturing the display and switching display mode
|
// flicker from capturing the display and switching display mode
|
||||||
|
@ -832,7 +844,6 @@ impl UnownedWindow {
|
||||||
trace!("Locked shared state in `set_fullscreen`");
|
trace!("Locked shared state in `set_fullscreen`");
|
||||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
||||||
shared_state_lock.fullscreen = fullscreen.clone();
|
shared_state_lock.fullscreen = fullscreen.clone();
|
||||||
trace!("Unlocked shared state in `set_fullscreen`");
|
|
||||||
|
|
||||||
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
|
@ -873,16 +884,42 @@ impl UnownedWindow {
|
||||||
// of the menu bar, and this looks broken, so we must make sure
|
// 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
|
// that the menu bar is disabled. This is done in the window
|
||||||
// delegate in `window:willUseFullScreenPresentationOptions:`.
|
// 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];
|
let () = msg_send![*self.ns_window, setLevel: ffi::CGShieldingWindowLevel() + 1];
|
||||||
},
|
},
|
||||||
(
|
(
|
||||||
&Some(Fullscreen::Exclusive(RootVideoMode { ref video_mode })),
|
&Some(Fullscreen::Exclusive(RootVideoMode { ref video_mode })),
|
||||||
&Some(Fullscreen::Borderless(_)),
|
&Some(Fullscreen::Borderless(_)),
|
||||||
) => unsafe {
|
) => unsafe {
|
||||||
|
let presentation_options =
|
||||||
|
shared_state_lock.save_presentation_opts.unwrap_or_else(|| {
|
||||||
|
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
|
||||||
|
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock
|
||||||
|
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar
|
||||||
|
});
|
||||||
|
NSApp().setPresentationOptions_(presentation_options);
|
||||||
|
|
||||||
util::restore_display_mode_async(video_mode.monitor().inner.native_identifier());
|
util::restore_display_mode_async(video_mode.monitor().inner.native_identifier());
|
||||||
|
|
||||||
|
// Restore the normal window level following the Borderless fullscreen
|
||||||
|
// `CGShieldingWindowLevel() + 1` hack.
|
||||||
|
let () = msg_send![
|
||||||
|
*self.ns_window,
|
||||||
|
setLevel: ffi::NSWindowLevel::NSNormalWindowLevel
|
||||||
|
];
|
||||||
},
|
},
|
||||||
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
|
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
|
||||||
}
|
};
|
||||||
|
trace!("Unlocked shared state in `set_fullscreen`");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -482,10 +482,10 @@ extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_will_use_fullscreen_presentation_options(
|
extern "C" fn window_will_use_fullscreen_presentation_options(
|
||||||
_this: &Object,
|
this: &Object,
|
||||||
_: Sel,
|
_: Sel,
|
||||||
_: id,
|
_: id,
|
||||||
_proposed_options: NSUInteger,
|
proposed_options: NSUInteger,
|
||||||
) -> NSUInteger {
|
) -> NSUInteger {
|
||||||
// Generally, games will want to disable the menu bar and the dock. Ideally,
|
// Generally, games will want to disable the menu bar and the dock. Ideally,
|
||||||
// this would be configurable by the user. Unfortunately because of our
|
// this would be configurable by the user. Unfortunately because of our
|
||||||
|
@ -495,10 +495,22 @@ extern "C" fn window_will_use_fullscreen_presentation_options(
|
||||||
// still want to make this configurable for borderless fullscreen. Right now
|
// 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
|
// we don't, for consistency. If we do, it should be documented that the
|
||||||
// user-provided options are ignored in exclusive fullscreen.
|
// user-provided options are ignored in exclusive fullscreen.
|
||||||
(NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
|
let mut options: NSUInteger = proposed_options;
|
||||||
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
|
with_state(this, |state| {
|
||||||
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar)
|
state.with_window(|window| {
|
||||||
.bits()
|
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
|
/// Invoked when entered fullscreen
|
||||||
|
|
Loading…
Reference in a new issue