Update objc2 crates (#3634)

Changes relevant to Winit:
- `icrate` has been deprecated in favour of separate crates per
  framework, in our case `objc2-foundation` and `objc2-app-kit` (and in
  the future `objc2-ui-kit` on iOS).
- Moved `MainThreadMarker::run_on_main` to free-standing function
  `run_on_main`.
- Changed how features work, this should result in less code that we
  need to compile.
- Enums are now real structs instead of type-aliases and free constants.
This commit is contained in:
Mads Marquart 2024-04-18 17:34:19 +02:00 committed by GitHub
parent 575d978202
commit 259e868c05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 289 additions and 270 deletions

View file

@ -4,29 +4,24 @@ use std::collections::VecDeque;
use std::ptr;
use core_graphics::display::{CGDisplay, CGPoint};
use icrate::AppKit::{
NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSApplication,
NSApplicationPresentationAutoHideDock, NSApplicationPresentationAutoHideMenuBar,
NSApplicationPresentationFullScreen, NSApplicationPresentationHideDock,
NSApplicationPresentationHideMenuBar, NSApplicationPresentationOptions, NSBackingStoreBuffered,
NSColor, NSCriticalRequest, NSDraggingDestination, NSFilenamesPboardType,
NSInformationalRequest, NSPasteboard, NSScreen, NSView, NSWindowAbove, NSWindowCloseButton,
NSWindowDelegate, NSWindowFullScreenButton, NSWindowLevel, NSWindowMiniaturizeButton,
NSWindowOcclusionStateVisible, NSWindowSharingNone, NSWindowSharingReadOnly, NSWindowStyleMask,
NSWindowStyleMaskBorderless, NSWindowStyleMaskClosable, NSWindowStyleMaskFullSizeContentView,
NSWindowStyleMaskMiniaturizable, NSWindowStyleMaskResizable, NSWindowStyleMaskTitled,
NSWindowTabbingModePreferred, NSWindowTitleHidden, NSWindowZoomButton,
};
use icrate::Foundation::{
CGFloat, MainThreadMarker, NSArray, NSCopying, NSObject, NSObjectProtocol, NSPoint, NSRect,
NSSize, NSString,
};
use monitor::VideoModeHandle;
use objc2::rc::{autoreleasepool, Id};
use objc2::runtime::{AnyObject, ProtocolObject};
use objc2::{
class, declare_class, msg_send, msg_send_id, mutability, sel, ClassType, DeclaredClass,
};
use objc2_app_kit::{
NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSApplication,
NSApplicationPresentationOptions, NSBackingStoreType, NSColor, NSDraggingDestination,
NSFilenamesPboardType, NSPasteboard, NSRequestUserAttentionType, NSScreen, NSView,
NSWindowButton, NSWindowDelegate, NSWindowFullScreenButton, NSWindowLevel,
NSWindowOcclusionState, NSWindowOrderingMode, NSWindowSharingType, NSWindowStyleMask,
NSWindowTabbingMode, NSWindowTitleVisibility,
};
use objc2_foundation::{
CGFloat, MainThreadMarker, NSArray, NSCopying, NSObject, NSObjectProtocol, NSPoint, NSRect,
NSSize, NSString,
};
use super::app_delegate::ApplicationDelegate;
use super::cursor::cursor_from_icon;
@ -266,9 +261,11 @@ declare_class!(
let mut options = proposed_options;
let fullscreen = self.ivars().fullscreen.borrow();
if let Some(Fullscreen::Exclusive(_)) = &*fullscreen {
options = NSApplicationPresentationFullScreen
| NSApplicationPresentationHideDock
| NSApplicationPresentationHideMenuBar;
options = NSApplicationPresentationOptions(
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar.0,
);
}
options
@ -337,8 +334,8 @@ declare_class!(
#[method(windowDidChangeOcclusionState:)]
fn window_did_change_occlusion_state(&self, _: Option<&AnyObject>) {
trace_scope!("windowDidChangeOcclusionState:");
let visible = self.window().occlusionState() & NSWindowOcclusionStateVisible
== NSWindowOcclusionStateVisible;
let visible = self.window().occlusionState().0 & NSWindowOcclusionState::Visible.0
== NSWindowOcclusionState::Visible.0;
self.queue_event(WindowEvent::Occluded(!visible));
}
@ -490,39 +487,39 @@ fn new_window(attrs: &WindowAttributes, mtm: MainThreadMarker) -> Option<Id<Wini
// if decorations is set to false, ignore pl_attrs
//
// if the titlebar is hidden, ignore other pl_attrs
NSWindowStyleMaskBorderless
| NSWindowStyleMaskResizable
| NSWindowStyleMaskMiniaturizable
NSWindowStyleMask::Borderless.0
| NSWindowStyleMask::Resizable.0
| NSWindowStyleMask::Miniaturizable.0
} else {
// default case, resizable window with titlebar and titlebar buttons
NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable
| NSWindowStyleMaskResizable
| NSWindowStyleMaskTitled
NSWindowStyleMask::Closable.0
| NSWindowStyleMask::Miniaturizable.0
| NSWindowStyleMask::Resizable.0
| NSWindowStyleMask::Titled.0
};
if !attrs.resizable {
masks &= !NSWindowStyleMaskResizable;
masks &= !NSWindowStyleMask::Resizable.0;
}
if !attrs.enabled_buttons.contains(WindowButtons::MINIMIZE) {
masks &= !NSWindowStyleMaskMiniaturizable;
masks &= !NSWindowStyleMask::Miniaturizable.0;
}
if !attrs.enabled_buttons.contains(WindowButtons::CLOSE) {
masks &= !NSWindowStyleMaskClosable;
masks &= !NSWindowStyleMask::Closable.0;
}
if attrs.platform_specific.fullsize_content_view {
masks |= NSWindowStyleMaskFullSizeContentView;
masks |= NSWindowStyleMask::FullSizeContentView.0;
}
let window: Option<Id<WinitWindow>> = unsafe {
msg_send_id![
super(mtm.alloc().set_ivars(())),
initWithContentRect: frame,
styleMask: masks,
backing: NSBackingStoreBuffered,
styleMask: NSWindowStyleMask(masks),
backing: NSBackingStoreType::NSBackingStoreBuffered,
defer: false,
]
};
@ -538,26 +535,26 @@ fn new_window(attrs: &WindowAttributes, mtm: MainThreadMarker) -> Option<Id<Wini
if let Some(identifier) = &attrs.platform_specific.tabbing_identifier {
window.setTabbingIdentifier(&NSString::from_str(identifier));
window.setTabbingMode(NSWindowTabbingModePreferred);
window.setTabbingMode(NSWindowTabbingMode::Preferred);
}
if attrs.content_protected {
window.setSharingType(NSWindowSharingNone);
window.setSharingType(NSWindowSharingType::NSWindowSharingNone);
}
if attrs.platform_specific.titlebar_transparent {
window.setTitlebarAppearsTransparent(true);
}
if attrs.platform_specific.title_hidden {
window.setTitleVisibility(NSWindowTitleHidden);
window.setTitleVisibility(NSWindowTitleVisibility::NSWindowTitleHidden);
}
if attrs.platform_specific.titlebar_buttons_hidden {
for titlebar_button in &[
#[allow(deprecated)]
NSWindowFullScreenButton,
NSWindowMiniaturizeButton,
NSWindowCloseButton,
NSWindowZoomButton,
NSWindowButton::NSWindowMiniaturizeButton,
NSWindowButton::NSWindowCloseButton,
NSWindowButton::NSWindowZoomButton,
] {
if let Some(button) = window.standardWindowButton(*titlebar_button) {
button.setHidden(true);
@ -569,7 +566,7 @@ fn new_window(attrs: &WindowAttributes, mtm: MainThreadMarker) -> Option<Id<Wini
}
if !attrs.enabled_buttons.contains(WindowButtons::MAXIMIZE) {
if let Some(button) = window.standardWindowButton(NSWindowZoomButton) {
if let Some(button) = window.standardWindowButton(NSWindowButton::NSWindowZoomButton) {
button.setEnabled(false);
}
}
@ -641,7 +638,9 @@ impl WindowDelegate {
// SAFETY: We know that there are no parent -> child -> parent cycles since the only place in `winit`
// where we allow making a window a child window is right here, just after it's been created.
unsafe { parent.addChildWindow_ordered(&window, NSWindowAbove) };
unsafe {
parent.addChildWindow_ordered(&window, NSWindowOrderingMode::NSWindowAbove)
};
}
Some(raw) => panic!("invalid raw window handle {raw:?} on macOS"),
None => (),
@ -975,13 +974,13 @@ impl WindowDelegate {
self.ivars().resizable.set(resizable);
let fullscreen = self.ivars().fullscreen.borrow().is_some();
if !fullscreen {
let mut mask = self.window().styleMask();
let mut mask = self.window().styleMask().0;
if resizable {
mask |= NSWindowStyleMaskResizable;
mask |= NSWindowStyleMask::Resizable.0;
} else {
mask &= !NSWindowStyleMaskResizable;
mask &= !NSWindowStyleMask::Resizable.0;
}
self.set_style_mask(mask);
self.set_style_mask(NSWindowStyleMask(mask));
}
// Otherwise, we don't change the mask until we exit fullscreen.
}
@ -993,28 +992,31 @@ impl WindowDelegate {
#[inline]
pub fn set_enabled_buttons(&self, buttons: WindowButtons) {
let mut mask = self.window().styleMask();
let mut mask = self.window().styleMask().0;
if buttons.contains(WindowButtons::CLOSE) {
mask |= NSWindowStyleMaskClosable;
mask |= NSWindowStyleMask::Closable.0;
} else {
mask &= !NSWindowStyleMaskClosable;
mask &= !NSWindowStyleMask::Closable.0;
}
if buttons.contains(WindowButtons::MINIMIZE) {
mask |= NSWindowStyleMaskMiniaturizable;
mask |= NSWindowStyleMask::Miniaturizable.0;
} else {
mask &= !NSWindowStyleMaskMiniaturizable;
mask &= !NSWindowStyleMask::Miniaturizable.0;
}
// This must happen before the button's "enabled" status has been set,
// hence we do it synchronously.
self.set_style_mask(mask);
self.set_style_mask(NSWindowStyleMask(mask));
// We edit the button directly instead of using `NSResizableWindowMask`,
// since that mask also affect the resizability of the window (which is
// controllable by other means in `winit`).
if let Some(button) = self.window().standardWindowButton(NSWindowZoomButton) {
if let Some(button) = self
.window()
.standardWindowButton(NSWindowButton::NSWindowZoomButton)
{
button.setEnabled(buttons.contains(WindowButtons::MAXIMIZE));
}
}
@ -1027,7 +1029,7 @@ impl WindowDelegate {
}
if self
.window()
.standardWindowButton(NSWindowZoomButton)
.standardWindowButton(NSWindowButton::NSWindowZoomButton)
.map(|b| b.isEnabled())
.unwrap_or(true)
{
@ -1131,7 +1133,8 @@ impl WindowDelegate {
// we make it resizable temporarily.
let curr_mask = self.window().styleMask();
let required = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable;
let required =
NSWindowStyleMask(NSWindowStyleMask::Titled.0 | NSWindowStyleMask::Resizable.0);
let needs_temp_mask = !mask_contains(curr_mask, required);
if needs_temp_mask {
self.set_style_mask(required);
@ -1152,12 +1155,13 @@ impl WindowDelegate {
.ivars()
.saved_style
.take()
.unwrap_or_else(|| self.window().styleMask());
if self.ivars().resizable.get() {
base_mask | NSWindowStyleMaskResizable
.unwrap_or_else(|| self.window().styleMask())
.0;
NSWindowStyleMask(if self.ivars().resizable.get() {
base_mask | NSWindowStyleMask::Resizable.0
} else {
base_mask & !NSWindowStyleMaskResizable
}
base_mask & !NSWindowStyleMask::Resizable.0
})
}
/// This is called when the window is exiting fullscreen, whether by the
@ -1212,7 +1216,7 @@ impl WindowDelegate {
return;
}
if mask_contains(self.window().styleMask(), NSWindowStyleMaskResizable) {
if mask_contains(self.window().styleMask(), NSWindowStyleMask::Resizable) {
// Just use the native zoom if resizable
self.window().zoom(None);
} else {
@ -1369,7 +1373,8 @@ impl WindowDelegate {
// set a normal style temporarily. The previous state will be
// restored in `WindowDelegate::window_did_exit_fullscreen`.
let curr_mask = self.window().styleMask();
let required = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable;
let required =
NSWindowStyleMask(NSWindowStyleMask::Titled.0 | NSWindowStyleMask::Resizable.0);
if !mask_contains(curr_mask, required) {
self.set_style_mask(required);
self.ivars().saved_style.set(Some(curr_mask));
@ -1403,9 +1408,11 @@ impl WindowDelegate {
.save_presentation_opts
.set(Some(app.presentationOptions()));
let presentation_options = NSApplicationPresentationFullScreen
| NSApplicationPresentationHideDock
| NSApplicationPresentationHideMenuBar;
let presentation_options = NSApplicationPresentationOptions(
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar.0,
);
app.setPresentationOptions(presentation_options);
let window_level = unsafe { ffi::CGShieldingWindowLevel() } as NSWindowLevel + 1;
@ -1413,9 +1420,9 @@ impl WindowDelegate {
}
(Some(Fullscreen::Exclusive(ref video_mode)), Some(Fullscreen::Borderless(_))) => {
let presentation_options = self.ivars().save_presentation_opts.get().unwrap_or(
NSApplicationPresentationFullScreen
| NSApplicationPresentationAutoHideDock
| NSApplicationPresentationAutoHideMenuBar,
NSApplicationPresentationOptions(NSApplicationPresentationOptions::NSApplicationPresentationFullScreen.0
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar.0),
);
app.setPresentationOptions(presentation_options);
@ -1455,19 +1462,19 @@ impl WindowDelegate {
let new_mask = {
let mut new_mask = if decorations {
NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable
| NSWindowStyleMaskResizable
| NSWindowStyleMaskTitled
NSWindowStyleMask::Closable.0
| NSWindowStyleMask::Miniaturizable.0
| NSWindowStyleMask::Resizable.0
| NSWindowStyleMask::Titled.0
} else {
NSWindowStyleMaskBorderless | NSWindowStyleMaskResizable
NSWindowStyleMask::Borderless.0 | NSWindowStyleMask::Resizable.0
};
if !resizable {
new_mask &= !NSWindowStyleMaskResizable;
new_mask &= !NSWindowStyleMask::Resizable.0;
}
new_mask
};
self.set_style_mask(new_mask);
self.set_style_mask(NSWindowStyleMask(new_mask));
}
#[inline]
@ -1534,8 +1541,8 @@ impl WindowDelegate {
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
let mtm = MainThreadMarker::from(self);
let ns_request_type = request_type.map(|ty| match ty {
UserAttentionType::Critical => NSCriticalRequest,
UserAttentionType::Informational => NSInformationalRequest,
UserAttentionType::Critical => NSRequestUserAttentionType::NSCriticalRequest,
UserAttentionType::Informational => NSRequestUserAttentionType::NSInformationalRequest,
});
if let Some(ty) = ns_request_type {
NSApplication::sharedApplication(mtm).requestUserAttention(ty);
@ -1602,9 +1609,9 @@ impl WindowDelegate {
fn toggle_style_mask(&self, mask: NSWindowStyleMask, on: bool) {
let current_style_mask = self.window().styleMask();
if on {
self.set_style_mask(current_style_mask | mask);
self.set_style_mask(NSWindowStyleMask(current_style_mask.0 | mask.0));
} else {
self.set_style_mask(current_style_mask & (!mask));
self.set_style_mask(NSWindowStyleMask(current_style_mask.0 & (!mask.0)));
}
}
@ -1629,9 +1636,9 @@ impl WindowDelegate {
#[inline]
pub fn set_content_protected(&self, protected: bool) {
self.window().setSharingType(if protected {
NSWindowSharingNone
NSWindowSharingType::NSWindowSharingNone
} else {
NSWindowSharingReadOnly
NSWindowSharingType::NSWindowSharingReadOnly
})
}
@ -1683,12 +1690,14 @@ impl WindowExtMacOS for WindowDelegate {
self.ivars().is_simple_fullscreen.set(true);
// Simulate pre-Lion fullscreen by hiding the dock and menu bar
let presentation_options =
NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar;
let presentation_options = NSApplicationPresentationOptions(
NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar.0,
);
app.setPresentationOptions(presentation_options);
// Hide the titlebar
self.toggle_style_mask(NSWindowStyleMaskTitled, false);
self.toggle_style_mask(NSWindowStyleMask::Titled, false);
// Set the window frame to the screen frame size
let screen = self
@ -1698,8 +1707,8 @@ impl WindowExtMacOS for WindowDelegate {
self.window().setFrame_display(screen.frame(), true);
// Fullscreen windows can't be resized, minimized, or moved
self.toggle_style_mask(NSWindowStyleMaskMiniaturizable, false);
self.toggle_style_mask(NSWindowStyleMaskResizable, false);
self.toggle_style_mask(NSWindowStyleMask::Miniaturizable, false);
self.toggle_style_mask(NSWindowStyleMask::Resizable, false);
self.window().setMovable(false);
true
@ -1793,7 +1802,7 @@ impl WindowExtMacOS for WindowDelegate {
}
fn mask_contains(mask: NSWindowStyleMask, value: NSWindowStyleMask) -> bool {
mask & value == value
mask.0 & value.0 == value.0
}
const DEFAULT_STANDARD_FRAME: NSRect =