macOS: add ability to make titlebar unified (#3960)
Adds `WindowExtMacOS::set_unified_titlebar` and `WindowAttributesExtMacOS::with_unified_titlebar`, which allow you to use a larger titlebar style on macOS.
This commit is contained in:
parent
c913cdab0b
commit
3e9b80d47a
4 changed files with 70 additions and 1 deletions
|
|
@ -136,6 +136,7 @@ objc2-app-kit = { version = "0.2.2", features = [
|
||||||
"NSScreen",
|
"NSScreen",
|
||||||
"NSTextInputClient",
|
"NSTextInputClient",
|
||||||
"NSTextInputContext",
|
"NSTextInputContext",
|
||||||
|
"NSToolbar",
|
||||||
"NSView",
|
"NSView",
|
||||||
"NSWindow",
|
"NSWindow",
|
||||||
"NSWindowScripting",
|
"NSWindowScripting",
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ changelog entry.
|
||||||
- Add a `standard_key_binding` method to the `ApplicationHandlerExtMacOS` trait. This allows handling of standard keybindings such as "go to end of line" on macOS.
|
- Add a `standard_key_binding` method to the `ApplicationHandlerExtMacOS` trait. This allows handling of standard keybindings such as "go to end of line" on macOS.
|
||||||
- On macOS, add `WindowExtMacOS::set_borderless_game` and `WindowAttributesExtMacOS::with_borderless_game`
|
- On macOS, add `WindowExtMacOS::set_borderless_game` and `WindowAttributesExtMacOS::with_borderless_game`
|
||||||
to fully disable the menu bar and dock in Borderless Fullscreen as commonly done in games.
|
to fully disable the menu bar and dock in Borderless Fullscreen as commonly done in games.
|
||||||
|
- On macOS, add `WindowExtMacOS::set_unified_titlebar` and `WindowAttributesExtMacOS::with_unified_titlebar`
|
||||||
|
to use a larger style of titlebar.
|
||||||
- Add `WindowId::into_raw()` and `from_raw()`.
|
- Add `WindowId::into_raw()` and `from_raw()`.
|
||||||
- Add `PointerKind`, `PointerSource`, `ButtonSource`, `FingerId` and `position` to all pointer
|
- Add `PointerKind`, `PointerSource`, `ButtonSource`, `FingerId` and `position` to all pointer
|
||||||
events as part of the pointer event overhaul.
|
events as part of the pointer event overhaul.
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,13 @@ pub trait WindowExtMacOS {
|
||||||
|
|
||||||
/// Getter for the [`WindowExtMacOS::set_borderless_game`].
|
/// Getter for the [`WindowExtMacOS::set_borderless_game`].
|
||||||
fn is_borderless_game(&self) -> bool;
|
fn is_borderless_game(&self) -> bool;
|
||||||
|
|
||||||
|
/// Makes the titlebar bigger, effectively adding more space around the
|
||||||
|
/// window controls if the titlebar is invisible.
|
||||||
|
fn set_unified_titlebar(&self, unified_titlebar: bool);
|
||||||
|
|
||||||
|
/// Getter for the [`WindowExtMacOS::set_unified_titlebar`].
|
||||||
|
fn unified_titlebar(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowExtMacOS for dyn Window + '_ {
|
impl WindowExtMacOS for dyn Window + '_ {
|
||||||
|
|
@ -255,6 +262,18 @@ impl WindowExtMacOS for dyn Window + '_ {
|
||||||
let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
|
let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
|
||||||
window.maybe_wait_on_main(|w| w.is_borderless_game())
|
window.maybe_wait_on_main(|w| w.is_borderless_game())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_unified_titlebar(&self, unified_titlebar: bool) {
|
||||||
|
let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
|
||||||
|
window.maybe_wait_on_main(|w| w.set_unified_titlebar(unified_titlebar))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unified_titlebar(&self) -> bool {
|
||||||
|
let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
|
||||||
|
window.maybe_wait_on_main(|w| w.unified_titlebar())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Corresponds to `NSApplicationActivationPolicy`.
|
/// Corresponds to `NSApplicationActivationPolicy`.
|
||||||
|
|
@ -308,6 +327,8 @@ pub trait WindowAttributesExtMacOS {
|
||||||
fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self;
|
fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self;
|
||||||
/// See [`WindowExtMacOS::set_borderless_game`] for details on what this means if set.
|
/// See [`WindowExtMacOS::set_borderless_game`] for details on what this means if set.
|
||||||
fn with_borderless_game(self, borderless_game: bool) -> Self;
|
fn with_borderless_game(self, borderless_game: bool) -> Self;
|
||||||
|
/// See [`WindowExtMacOS::set_unified_titlebar`] for details on what this means if set.
|
||||||
|
fn with_unified_titlebar(self, unified_titlebar: bool) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowAttributesExtMacOS for WindowAttributes {
|
impl WindowAttributesExtMacOS for WindowAttributes {
|
||||||
|
|
@ -382,6 +403,12 @@ impl WindowAttributesExtMacOS for WindowAttributes {
|
||||||
self.platform_specific.borderless_game = borderless_game;
|
self.platform_specific.borderless_game = borderless_game;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_unified_titlebar(mut self, unified_titlebar: bool) -> Self {
|
||||||
|
self.platform_specific.unified_titlebar = unified_titlebar;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EventLoopBuilderExtMacOS {
|
pub trait EventLoopBuilderExtMacOS {
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,10 @@ use objc2_app_kit::{
|
||||||
NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSAppearanceCustomization,
|
NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSAppearanceCustomization,
|
||||||
NSAppearanceNameAqua, NSApplication, NSApplicationPresentationOptions, NSBackingStoreType,
|
NSAppearanceNameAqua, NSApplication, NSApplicationPresentationOptions, NSBackingStoreType,
|
||||||
NSColor, NSDraggingDestination, NSFilenamesPboardType, NSPasteboard,
|
NSColor, NSDraggingDestination, NSFilenamesPboardType, NSPasteboard,
|
||||||
NSRequestUserAttentionType, NSScreen, NSView, NSWindowButton, NSWindowDelegate,
|
NSRequestUserAttentionType, NSScreen, NSToolbar, NSView, NSWindowButton, NSWindowDelegate,
|
||||||
NSWindowFullScreenButton, NSWindowLevel, NSWindowOcclusionState, NSWindowOrderingMode,
|
NSWindowFullScreenButton, NSWindowLevel, NSWindowOcclusionState, NSWindowOrderingMode,
|
||||||
NSWindowSharingType, NSWindowStyleMask, NSWindowTabbingMode, NSWindowTitleVisibility,
|
NSWindowSharingType, NSWindowStyleMask, NSWindowTabbingMode, NSWindowTitleVisibility,
|
||||||
|
NSWindowToolbarStyle,
|
||||||
};
|
};
|
||||||
use objc2_foundation::{
|
use objc2_foundation::{
|
||||||
ns_string, CGFloat, MainThreadMarker, NSArray, NSCopying, NSDictionary, NSKeyValueChangeKey,
|
ns_string, CGFloat, MainThreadMarker, NSArray, NSCopying, NSDictionary, NSKeyValueChangeKey,
|
||||||
|
|
@ -57,6 +58,7 @@ pub struct PlatformSpecificWindowAttributes {
|
||||||
pub tabbing_identifier: Option<String>,
|
pub tabbing_identifier: Option<String>,
|
||||||
pub option_as_alt: OptionAsAlt,
|
pub option_as_alt: OptionAsAlt,
|
||||||
pub borderless_game: bool,
|
pub borderless_game: bool,
|
||||||
|
pub unified_titlebar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlatformSpecificWindowAttributes {
|
impl Default for PlatformSpecificWindowAttributes {
|
||||||
|
|
@ -75,6 +77,7 @@ impl Default for PlatformSpecificWindowAttributes {
|
||||||
tabbing_identifier: None,
|
tabbing_identifier: None,
|
||||||
option_as_alt: Default::default(),
|
option_as_alt: Default::default(),
|
||||||
borderless_game: false,
|
borderless_game: false,
|
||||||
|
unified_titlebar: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -616,6 +619,14 @@ fn new_window(
|
||||||
if attrs.platform_specific.movable_by_window_background {
|
if attrs.platform_specific.movable_by_window_background {
|
||||||
window.setMovableByWindowBackground(true);
|
window.setMovableByWindowBackground(true);
|
||||||
}
|
}
|
||||||
|
if attrs.platform_specific.unified_titlebar {
|
||||||
|
unsafe {
|
||||||
|
// The toolbar style is ignored if there is no toolbar, so it is
|
||||||
|
// necessary to add one.
|
||||||
|
window.setToolbar(Some(&NSToolbar::new(mtm)));
|
||||||
|
window.setToolbarStyle(NSWindowToolbarStyle::Unified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !attrs.enabled_buttons.contains(WindowButtons::MAXIMIZE) {
|
if !attrs.enabled_buttons.contains(WindowButtons::MAXIMIZE) {
|
||||||
if let Some(button) = window.standardWindowButton(NSWindowButton::NSWindowZoomButton) {
|
if let Some(button) = window.standardWindowButton(NSWindowButton::NSWindowZoomButton) {
|
||||||
|
|
@ -1837,6 +1848,34 @@ impl WindowExtMacOS for WindowDelegate {
|
||||||
fn is_borderless_game(&self) -> bool {
|
fn is_borderless_game(&self) -> bool {
|
||||||
self.ivars().is_borderless_game.get()
|
self.ivars().is_borderless_game.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_unified_titlebar(&self, unified_titlebar: bool) {
|
||||||
|
let window = self.window();
|
||||||
|
|
||||||
|
if unified_titlebar {
|
||||||
|
let mtm = MainThreadMarker::from(self);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// The toolbar style is ignored if there is no toolbar, so it is
|
||||||
|
// necessary to add one.
|
||||||
|
window.setToolbar(Some(&NSToolbar::new(mtm)));
|
||||||
|
window.setToolbarStyle(NSWindowToolbarStyle::Unified);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
window.setToolbar(None);
|
||||||
|
window.setToolbarStyle(NSWindowToolbarStyle::Automatic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unified_titlebar(&self) -> bool {
|
||||||
|
let window = self.window();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
window.toolbar().is_some() && window.toolbarStyle() == NSWindowToolbarStyle::Unified
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_STANDARD_FRAME: NSRect =
|
const DEFAULT_STANDARD_FRAME: NSRect =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue