Update objc2 to v0.2.2 (#3702)

- Use new `bitflags!` support.
- Use `objc2-ui-kit`.
- Change usage of `Id` to `Retained`.
This commit is contained in:
Mads Marquart 2024-05-27 14:49:22 +02:00 committed by GitHub
parent 5ea20fc905
commit d7abe0316e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 332 additions and 1056 deletions

View file

@ -5,7 +5,6 @@ use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, N
use objc2_foundation::{MainThreadMarker, NSObject};
use super::app_delegate::ApplicationDelegate;
use super::event::flags_contains;
use crate::event::{DeviceEvent, ElementState};
declare_class!(
@ -32,7 +31,7 @@ declare_class!(
let event_type = unsafe { event.r#type() };
let modifier_flags = unsafe { event.modifierFlags() };
if event_type == NSEventType::KeyUp
&& flags_contains(modifier_flags, NSEventModifierFlags::NSEventModifierFlagCommand)
&& modifier_flags.contains(NSEventModifierFlags::NSEventModifierFlagCommand)
{
if let Some(key_window) = self.keyWindow() {
key_window.sendEvent(event);

View file

@ -5,7 +5,7 @@ use std::rc::Weak;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use objc2::rc::Id;
use objc2::rc::Retained;
use objc2::runtime::AnyObject;
use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass};
use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate};
@ -133,7 +133,7 @@ impl ApplicationDelegate {
activation_policy: NSApplicationActivationPolicy,
default_menu: bool,
activate_ignoring_other_apps: bool,
) -> Id<Self> {
) -> Retained<Self> {
let this = mtm.alloc().set_ivars(State {
activation_policy: Policy(activation_policy),
default_menu,
@ -143,13 +143,13 @@ impl ApplicationDelegate {
unsafe { msg_send_id![super(this), init] }
}
pub fn get(mtm: MainThreadMarker) -> Id<Self> {
pub fn get(mtm: MainThreadMarker) -> Retained<Self> {
let app = NSApplication::sharedApplication(mtm);
let delegate =
unsafe { app.delegate() }.expect("a delegate was not configured on the application");
if delegate.is_kind_of::<Self>() {
// SAFETY: Just checked that the delegate is an instance of `ApplicationDelegate`
unsafe { Id::cast(delegate) }
unsafe { Retained::cast(delegate) }
} else {
panic!("tried to get a delegate that was not the one Winit has registered")
}
@ -247,7 +247,7 @@ impl ApplicationDelegate {
pub fn queue_static_scale_factor_changed_event(
&self,
window: Id<WinitWindow>,
window: Retained<WinitWindow>,
suggested_size: PhysicalSize<u32>,
scale_factor: f64,
) {
@ -425,7 +425,7 @@ pub(crate) enum QueuedEvent {
WindowEvent(WindowId, WindowEvent),
DeviceEvent(DeviceEvent),
ScaleFactorChanged {
window: Id<WinitWindow>,
window: Retained<WinitWindow>,
suggested_size: PhysicalSize<u32>,
scale_factor: f64,
},

View file

@ -2,7 +2,7 @@ use std::ffi::c_uchar;
use std::slice;
use std::sync::OnceLock;
use objc2::rc::Id;
use objc2::rc::Retained;
use objc2::runtime::Sel;
use objc2::{msg_send_id, sel, ClassType};
use objc2_app_kit::{NSBitmapImageRep, NSCursor, NSDeviceRGBColorSpace, NSImage};
@ -15,7 +15,7 @@ use crate::cursor::{CursorImage, OnlyCursorImageSource};
use crate::window::CursorIcon;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct CustomCursor(pub(crate) Id<NSCursor>);
pub struct CustomCursor(pub(crate) Retained<NSCursor>);
// SAFETY: NSCursor is immutable and thread-safe
// TODO(madsmtm): Put this logic in objc2-app-kit itself
@ -28,7 +28,7 @@ impl CustomCursor {
}
}
pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Id<NSCursor> {
pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Retained<NSCursor> {
let width = cursor.width;
let height = cursor.height;
@ -60,14 +60,14 @@ pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Id<NSCursor> {
NSCursor::initWithImage_hotSpot(NSCursor::alloc(), &image, hotspot)
}
pub(crate) fn default_cursor() -> Id<NSCursor> {
pub(crate) fn default_cursor() -> Retained<NSCursor> {
NSCursor::arrowCursor()
}
unsafe fn try_cursor_from_selector(sel: Sel) -> Option<Id<NSCursor>> {
unsafe fn try_cursor_from_selector(sel: Sel) -> Option<Retained<NSCursor>> {
let cls = NSCursor::class();
if cls.responds_to(sel) {
let cursor: Id<NSCursor> = unsafe { msg_send_id![cls, performSelector: sel] };
let cursor: Retained<NSCursor> = unsafe { msg_send_id![cls, performSelector: sel] };
Some(cursor)
} else {
tracing::warn!("cursor `{sel}` appears to be invalid");
@ -82,7 +82,7 @@ macro_rules! def_undocumented_cursor {
)*} => {$(
$(#[$($m)*])*
#[allow(non_snake_case)]
fn $name() -> Id<NSCursor> {
fn $name() -> Retained<NSCursor> {
unsafe { try_cursor_from_selector(sel!($name)).unwrap_or_else(|| default_cursor()) }
}
)*};
@ -112,7 +112,7 @@ def_undocumented_cursor!(
// Note that loading `busybutclickable` with this code won't animate
// the frames; instead you'll just get them all in a column.
unsafe fn load_webkit_cursor(name: &NSString) -> Id<NSCursor> {
unsafe fn load_webkit_cursor(name: &NSString) -> Retained<NSCursor> {
// Snatch a cursor from WebKit; They fit the style of the native
// cursors, and will seem completely standard to macOS users.
//
@ -128,7 +128,7 @@ unsafe fn load_webkit_cursor(name: &NSString) -> Id<NSCursor> {
// TODO: Handle PLists better
let info_path = cursor_path.stringByAppendingPathComponent(ns_string!("info.plist"));
let info: Id<NSDictionary<NSObject, NSObject>> = unsafe {
let info: Retained<NSDictionary<NSObject, NSObject>> = unsafe {
msg_send_id![
<NSDictionary<NSObject, NSObject>>::class(),
dictionaryWithContentsOfFile: &*info_path,
@ -155,15 +155,15 @@ unsafe fn load_webkit_cursor(name: &NSString) -> Id<NSCursor> {
NSCursor::initWithImage_hotSpot(NSCursor::alloc(), &image, hotspot)
}
fn webkit_move() -> Id<NSCursor> {
fn webkit_move() -> Retained<NSCursor> {
unsafe { load_webkit_cursor(ns_string!("move")) }
}
fn webkit_cell() -> Id<NSCursor> {
fn webkit_cell() -> Retained<NSCursor> {
unsafe { load_webkit_cursor(ns_string!("cell")) }
}
pub(crate) fn invisible_cursor() -> Id<NSCursor> {
pub(crate) fn invisible_cursor() -> Retained<NSCursor> {
// 16x16 GIF data for invisible cursor
// You can reproduce this via ImageMagick.
// $ convert -size 16x16 xc:none cursor.gif
@ -174,7 +174,7 @@ pub(crate) fn invisible_cursor() -> Id<NSCursor> {
0xa3, 0x9c, 0xb4, 0xda, 0x8b, 0xb3, 0x3e, 0x05, 0x00, 0x3b,
];
fn new_invisible() -> Id<NSCursor> {
fn new_invisible() -> Retained<NSCursor> {
// TODO: Consider using `dataWithBytesNoCopy:`
let data = NSData::with_bytes(CURSOR_BYTES);
let image = NSImage::initWithData(NSImage::alloc(), &data).unwrap();
@ -187,7 +187,7 @@ pub(crate) fn invisible_cursor() -> Id<NSCursor> {
CURSOR.get_or_init(|| CustomCursor(new_invisible())).0.clone()
}
pub(crate) fn cursor_from_icon(icon: CursorIcon) -> Id<NSCursor> {
pub(crate) fn cursor_from_icon(icon: CursorIcon) -> Retained<NSCursor> {
match icon {
CursorIcon::Default => default_cursor(),
CursorIcon::Pointer => NSCursor::pointingHandCursor(),

View file

@ -2,7 +2,7 @@ use std::ffi::c_void;
use core_foundation::base::CFRelease;
use core_foundation::data::{CFDataGetBytePtr, CFDataRef};
use objc2::rc::Id;
use objc2::rc::Retained;
use objc2_app_kit::{NSEvent, NSEventModifierFlags, NSEventSubtype, NSEventType};
use objc2_foundation::{run_on_main, NSPoint};
use smol_str::SmolStr;
@ -133,8 +133,8 @@ pub(crate) fn create_key_event(
let key_without_modifiers = get_modifierless_char(scancode);
let modifiers = unsafe { ns_event.modifierFlags() };
let has_ctrl = flags_contains(modifiers, NSEventModifierFlags::NSEventModifierFlagControl);
let has_cmd = flags_contains(modifiers, NSEventModifierFlags::NSEventModifierFlagCommand);
let has_ctrl = modifiers.contains(NSEventModifierFlags::NSEventModifierFlagControl);
let has_cmd = modifiers.contains(NSEventModifierFlags::NSEventModifierFlagCommand);
let logical_key = match text_with_all_modifiers.as_ref() {
// Only checking for ctrl and cmd here, not checking for alt because we DO want to
@ -305,16 +305,12 @@ const NX_DEVICELALTKEYMASK: NSEventModifierFlags = NSEventModifierFlags(0x000000
const NX_DEVICERALTKEYMASK: NSEventModifierFlags = NSEventModifierFlags(0x00000040);
const NX_DEVICERCTLKEYMASK: NSEventModifierFlags = NSEventModifierFlags(0x00002000);
pub(super) fn flags_contains(flags: NSEventModifierFlags, value: NSEventModifierFlags) -> bool {
flags.0 & value.0 == value.0
}
pub(super) fn lalt_pressed(event: &NSEvent) -> bool {
flags_contains(unsafe { event.modifierFlags() }, NX_DEVICELALTKEYMASK)
unsafe { event.modifierFlags() }.contains(NX_DEVICELALTKEYMASK)
}
pub(super) fn ralt_pressed(event: &NSEvent) -> bool {
flags_contains(unsafe { event.modifierFlags() }, NX_DEVICERALTKEYMASK)
unsafe { event.modifierFlags() }.contains(NX_DEVICERALTKEYMASK)
}
pub(super) fn event_mods(event: &NSEvent) -> Modifiers {
@ -322,38 +318,33 @@ pub(super) fn event_mods(event: &NSEvent) -> Modifiers {
let mut state = ModifiersState::empty();
let mut pressed_mods = ModifiersKeys::empty();
state.set(
ModifiersState::SHIFT,
flags_contains(flags, NSEventModifierFlags::NSEventModifierFlagShift),
);
pressed_mods.set(ModifiersKeys::LSHIFT, flags_contains(flags, NX_DEVICELSHIFTKEYMASK));
pressed_mods.set(ModifiersKeys::RSHIFT, flags_contains(flags, NX_DEVICERSHIFTKEYMASK));
state
.set(ModifiersState::SHIFT, flags.contains(NSEventModifierFlags::NSEventModifierFlagShift));
pressed_mods.set(ModifiersKeys::LSHIFT, flags.contains(NX_DEVICELSHIFTKEYMASK));
pressed_mods.set(ModifiersKeys::RSHIFT, flags.contains(NX_DEVICERSHIFTKEYMASK));
state.set(
ModifiersState::CONTROL,
flags_contains(flags, NSEventModifierFlags::NSEventModifierFlagControl),
flags.contains(NSEventModifierFlags::NSEventModifierFlagControl),
);
pressed_mods.set(ModifiersKeys::LCONTROL, flags_contains(flags, NX_DEVICELCTLKEYMASK));
pressed_mods.set(ModifiersKeys::RCONTROL, flags_contains(flags, NX_DEVICERCTLKEYMASK));
pressed_mods.set(ModifiersKeys::LCONTROL, flags.contains(NX_DEVICELCTLKEYMASK));
pressed_mods.set(ModifiersKeys::RCONTROL, flags.contains(NX_DEVICERCTLKEYMASK));
state.set(
ModifiersState::ALT,
flags_contains(flags, NSEventModifierFlags::NSEventModifierFlagOption),
);
pressed_mods.set(ModifiersKeys::LALT, flags_contains(flags, NX_DEVICELALTKEYMASK));
pressed_mods.set(ModifiersKeys::RALT, flags_contains(flags, NX_DEVICERALTKEYMASK));
state.set(ModifiersState::ALT, flags.contains(NSEventModifierFlags::NSEventModifierFlagOption));
pressed_mods.set(ModifiersKeys::LALT, flags.contains(NX_DEVICELALTKEYMASK));
pressed_mods.set(ModifiersKeys::RALT, flags.contains(NX_DEVICERALTKEYMASK));
state.set(
ModifiersState::SUPER,
flags_contains(flags, NSEventModifierFlags::NSEventModifierFlagCommand),
flags.contains(NSEventModifierFlags::NSEventModifierFlagCommand),
);
pressed_mods.set(ModifiersKeys::LSUPER, flags_contains(flags, NX_DEVICELCMDKEYMASK));
pressed_mods.set(ModifiersKeys::RSUPER, flags_contains(flags, NX_DEVICERCMDKEYMASK));
pressed_mods.set(ModifiersKeys::LSUPER, flags.contains(NX_DEVICELCMDKEYMASK));
pressed_mods.set(ModifiersKeys::RSUPER, flags.contains(NX_DEVICERCMDKEYMASK));
Modifiers { state, pressed_mods }
}
pub(super) fn dummy_event() -> Option<Id<NSEvent>> {
pub(super) fn dummy_event() -> Option<Retained<NSEvent>> {
unsafe {
NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
NSEventType::ApplicationDefined,

View file

@ -14,7 +14,7 @@ use core_foundation::runloop::{
kCFRunLoopCommonModes, CFRunLoopAddSource, CFRunLoopGetMain, CFRunLoopSourceContext,
CFRunLoopSourceCreate, CFRunLoopSourceRef, CFRunLoopSourceSignal, CFRunLoopWakeUp,
};
use objc2::rc::{autoreleasepool, Id};
use objc2::rc::{autoreleasepool, Retained};
use objc2::runtime::ProtocolObject;
use objc2::{msg_send_id, ClassType};
use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSWindow};
@ -68,12 +68,12 @@ impl PanicInfo {
#[derive(Debug)]
pub struct ActiveEventLoop {
delegate: Id<ApplicationDelegate>,
delegate: Retained<ApplicationDelegate>,
pub(super) mtm: MainThreadMarker,
}
impl ActiveEventLoop {
pub(super) fn new_root(delegate: Id<ApplicationDelegate>) -> RootWindowTarget {
pub(super) fn new_root(delegate: Retained<ApplicationDelegate>) -> RootWindowTarget {
let mtm = MainThreadMarker::from(&*delegate);
let p = Self { delegate, mtm };
RootWindowTarget { p, _marker: PhantomData }
@ -186,12 +186,12 @@ pub struct EventLoop<T: 'static> {
///
/// We intentionally don't store `WinitApplication` since we want to have
/// the possibility of swapping that out at some point.
app: Id<NSApplication>,
app: Retained<NSApplication>,
/// The application delegate that we've registered.
///
/// The delegate is only weakly referenced by NSApplication, so we must
/// keep it around here as well.
delegate: Id<ApplicationDelegate>,
delegate: Retained<ApplicationDelegate>,
// Event sender and receiver, used for EventLoopProxy.
sender: mpsc::Sender<T>,
@ -225,7 +225,7 @@ impl<T> EventLoop<T> {
let mtm = MainThreadMarker::new()
.expect("on macOS, `EventLoop` must be created on the main thread!");
let app: Id<NSApplication> =
let app: Retained<NSApplication> =
unsafe { msg_send_id![WinitApplication::class(), sharedApplication] };
if !app.is_kind_of::<WinitApplication>() {

View file

@ -1,4 +1,4 @@
use objc2::rc::Id;
use objc2::rc::Retained;
use objc2::runtime::Sel;
use objc2::sel;
use objc2_app_kit::{NSApplication, NSEventModifierFlags, NSMenu, NSMenuItem};
@ -48,10 +48,10 @@ pub fn initialize(app: &NSApplication) {
Some(sel!(hideOtherApplications:)),
Some(KeyEquivalent {
key: ns_string!("h"),
masks: Some(NSEventModifierFlags(
NSEventModifierFlags::NSEventModifierFlagOption.0
| NSEventModifierFlags::NSEventModifierFlagCommand.0,
)),
masks: Some(
NSEventModifierFlags::NSEventModifierFlagOption
| NSEventModifierFlags::NSEventModifierFlagCommand,
),
}),
);
@ -91,7 +91,7 @@ fn menu_item(
title: &NSString,
selector: Option<Sel>,
key_equivalent: Option<KeyEquivalent<'_>>,
) -> Id<NSMenuItem> {
) -> Retained<NSMenuItem> {
let (key, masks) = match key_equivalent {
Some(ke) => (ke.key, ke.masks),
None => (ns_string!(""), None),

View file

@ -9,7 +9,7 @@ use core_foundation::string::CFString;
use core_graphics::display::{
CGDirectDisplayID, CGDisplay, CGDisplayBounds, CGDisplayCopyDisplayMode,
};
use objc2::rc::Id;
use objc2::rc::Retained;
use objc2::runtime::AnyObject;
use objc2_app_kit::NSScreen;
use objc2_foundation::{ns_string, run_on_main, MainThreadMarker, NSNumber, NSPoint, NSRect};
@ -295,7 +295,7 @@ impl MonitorHandle {
}
}
pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option<Id<NSScreen>> {
pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option<Retained<NSScreen>> {
let uuid = unsafe { ffi::CGDisplayCreateUUIDFromDisplayID(self.0) };
NSScreen::screens(mtm).into_iter().find(|screen| {
let other_native_id = get_display_id(screen);

View file

@ -3,7 +3,7 @@ use std::cell::{Cell, RefCell};
use std::collections::{HashMap, VecDeque};
use std::ptr;
use objc2::rc::{Id, WeakId};
use objc2::rc::{Retained, WeakId};
use objc2::runtime::{AnyObject, Sel};
use objc2::{declare_class, msg_send_id, mutability, sel, ClassType, DeclaredClass};
use objc2_app_kit::{
@ -35,7 +35,7 @@ use crate::platform::macos::OptionAsAlt;
#[derive(Debug)]
struct CursorState {
visible: bool,
cursor: Id<NSCursor>,
cursor: Retained<NSCursor>,
}
impl Default for CursorState {
@ -111,7 +111,7 @@ fn get_left_modifier_code(key: &Key) -> KeyCode {
#[derive(Debug)]
pub struct ViewState {
/// Strong reference to the global application state.
app_delegate: Id<ApplicationDelegate>,
app_delegate: Retained<ApplicationDelegate>,
cursor_state: RefCell<CursorState>,
ime_position: Cell<NSPoint>,
@ -131,7 +131,7 @@ pub struct ViewState {
/// to the application, even during IME
forward_key_to_app: Cell<bool>,
marked_text: RefCell<Id<NSMutableAttributedString>>,
marked_text: RefCell<Retained<NSMutableAttributedString>>,
accepts_first_mouse: bool,
// Weak reference because the window keeps a strong reference to the view
@ -221,7 +221,7 @@ declare_class!(
// IMKInputSession [0x7fc573576ff0 presentFunctionRowItemTextInputViewWithEndpoint:completionHandler:] : [self textInputContext]=0x7fc573558e10 *NO* NSRemoteViewController to client, NSError=Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 0 was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 0 was invalidated from this process.}, com.apple.inputmethod.EmojiFunctionRowItem
// TODO: Add an API extension for using `NSTouchBar`
#[method_id(touchBar)]
fn touch_bar(&self) -> Option<Id<NSObject>> {
fn touch_bar(&self) -> Option<Retained<NSObject>> {
trace_scope!("touchBar");
None
}
@ -340,7 +340,7 @@ declare_class!(
}
#[method_id(validAttributesForMarkedText)]
fn valid_attributes_for_marked_text(&self) -> Id<NSArray<NSAttributedStringKey>> {
fn valid_attributes_for_marked_text(&self) -> Retained<NSArray<NSAttributedStringKey>> {
trace_scope!("validAttributesForMarkedText");
NSArray::new()
}
@ -350,7 +350,7 @@ declare_class!(
&self,
_range: NSRange,
_actual_range: *mut NSRange,
) -> Option<Id<NSAttributedString>> {
) -> Option<Retained<NSAttributedString>> {
trace_scope!("attributedSubstringForProposedRange:actualRange:");
None
}
@ -776,7 +776,7 @@ impl WinitView {
window: &WinitWindow,
accepts_first_mouse: bool,
option_as_alt: OptionAsAlt,
) -> Id<Self> {
) -> Retained<Self> {
let mtm = MainThreadMarker::from(window);
let this = mtm.alloc().set_ivars(ViewState {
app_delegate: app_delegate.retain(),
@ -795,7 +795,7 @@ impl WinitView {
_ns_window: WeakId::new(&window.retain()),
option_as_alt: Cell::new(option_as_alt),
});
let this: Id<Self> = unsafe { msg_send_id![super(this), init] };
let this: Retained<Self> = unsafe { msg_send_id![super(this), init] };
this.setPostsFrameChangedNotifications(true);
let notification_center = unsafe { NSNotificationCenter::defaultCenter() };
@ -813,7 +813,7 @@ impl WinitView {
this
}
fn window(&self) -> Id<WinitWindow> {
fn window(&self) -> Retained<WinitWindow> {
// TODO: Simply use `window` property on `NSView`.
// That only returns a window _after_ the view has been attached though!
// (which is incompatible with `frameDidChange:`)
@ -846,11 +846,11 @@ impl WinitView {
.unwrap_or_default()
}
pub(super) fn cursor_icon(&self) -> Id<NSCursor> {
pub(super) fn cursor_icon(&self) -> Retained<NSCursor> {
self.ivars().cursor_state.borrow().cursor.clone()
}
pub(super) fn set_cursor_icon(&self, icon: Id<NSCursor>) {
pub(super) fn set_cursor_icon(&self, icon: Retained<NSCursor>) {
let mut cursor_state = self.ivars().cursor_state.borrow_mut();
cursor_state.cursor = icon;
}
@ -1083,7 +1083,7 @@ fn mouse_button(event: &NSEvent) -> MouseButton {
// NOTE: to get option as alt working we need to rewrite events
// we're getting from the operating system, which makes it
// impossible to provide such events as extra in `KeyEvent`.
fn replace_event(event: &NSEvent, option_as_alt: OptionAsAlt) -> Id<NSEvent> {
fn replace_event(event: &NSEvent, option_as_alt: OptionAsAlt) -> Retained<NSEvent> {
let ev_mods = event_mods(event).state;
let ignore_alt_characters = match option_as_alt {
OptionAsAlt::OnlyLeft if lalt_pressed(event) => true,

View file

@ -1,6 +1,6 @@
#![allow(clippy::unnecessary_cast)]
use objc2::rc::{autoreleasepool, Id};
use objc2::rc::{autoreleasepool, Retained};
use objc2::{declare_class, mutability, ClassType, DeclaredClass};
use objc2_app_kit::{NSResponder, NSWindow};
use objc2_foundation::{MainThreadBound, MainThreadMarker, NSObject};
@ -11,9 +11,9 @@ use crate::error::OsError as RootOsError;
use crate::window::WindowAttributes;
pub(crate) struct Window {
window: MainThreadBound<Id<WinitWindow>>,
window: MainThreadBound<Retained<WinitWindow>>,
/// The window only keeps a weak reference to this, so we must keep it around here.
delegate: MainThreadBound<Id<WindowDelegate>>,
delegate: MainThreadBound<Retained<WindowDelegate>>,
}
impl Drop for Window {

View file

@ -4,7 +4,7 @@ use std::collections::VecDeque;
use core_graphics::display::{CGDisplay, CGPoint};
use monitor::VideoModeHandle;
use objc2::rc::{autoreleasepool, Id};
use objc2::rc::{autoreleasepool, Retained};
use objc2::runtime::{AnyObject, ProtocolObject};
use objc2::{declare_class, msg_send_id, mutability, sel, ClassType, DeclaredClass};
use objc2_app_kit::{
@ -73,9 +73,9 @@ impl Default for PlatformSpecificWindowAttributes {
#[derive(Debug)]
pub(crate) struct State {
/// Strong reference to the global application state.
app_delegate: Id<ApplicationDelegate>,
app_delegate: Retained<ApplicationDelegate>,
window: Id<WinitWindow>,
window: Retained<WinitWindow>,
current_theme: Cell<Option<Theme>>,
@ -231,7 +231,7 @@ declare_class!(
None => {
let current_monitor = self.current_monitor_inner();
*fullscreen = Some(Fullscreen::Borderless(current_monitor));
}
},
}
self.ivars().in_fullscreen_transition.set(true);
}
@ -262,11 +262,9 @@ declare_class!(
let mut options = proposed_options;
let fullscreen = self.ivars().fullscreen.borrow();
if let Some(Fullscreen::Exclusive(_)) = &*fullscreen {
options = NSApplicationPresentationOptions(
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar.0,
);
options = NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar;
}
options
@ -333,8 +331,7 @@ declare_class!(
#[method(windowDidChangeOcclusionState:)]
fn window_did_change_occlusion_state(&self, _: Option<&AnyObject>) {
trace_scope!("windowDidChangeOcclusionState:");
let visible = self.window().occlusionState().0 & NSWindowOcclusionState::Visible.0
== NSWindowOcclusionState::Visible.0;
let visible = self.window().occlusionState().contains(NSWindowOcclusionState::Visible);
self.queue_event(WindowEvent::Occluded(!visible));
}
@ -358,11 +355,9 @@ declare_class!(
use std::path::PathBuf;
let pb: Id<NSPasteboard> = unsafe { msg_send_id![sender, draggingPasteboard] };
let filenames = pb
.propertyListForType(unsafe { NSFilenamesPboardType })
.unwrap();
let filenames: Id<NSArray<NSString>> = unsafe { Id::cast(filenames) };
let pb: Retained<NSPasteboard> = unsafe { msg_send_id![sender, draggingPasteboard] };
let filenames = pb.propertyListForType(unsafe { NSFilenamesPboardType }).unwrap();
let filenames: Retained<NSArray<NSString>> = unsafe { Retained::cast(filenames) };
filenames.into_iter().for_each(|file| {
let path = PathBuf::from(file.to_string());
@ -386,11 +381,9 @@ declare_class!(
use std::path::PathBuf;
let pb: Id<NSPasteboard> = unsafe { msg_send_id![sender, draggingPasteboard] };
let filenames = pb
.propertyListForType(unsafe { NSFilenamesPboardType })
.unwrap();
let filenames: Id<NSArray<NSString>> = unsafe { Id::cast(filenames) };
let pb: Retained<NSPasteboard> = unsafe { msg_send_id![sender, draggingPasteboard] };
let filenames = pb.propertyListForType(unsafe { NSFilenamesPboardType }).unwrap();
let filenames: Retained<NSArray<NSString>> = unsafe { Retained::cast(filenames) };
filenames.into_iter().for_each(|file| {
let path = PathBuf::from(file.to_string());
@ -444,7 +437,7 @@ fn new_window(
app_delegate: &ApplicationDelegate,
attrs: &WindowAttributes,
mtm: MainThreadMarker,
) -> Option<Id<WinitWindow>> {
) -> Option<Retained<WinitWindow>> {
autoreleasepool(|_| {
let screen = match attrs.fullscreen.clone().map(Into::into) {
Some(Fullscreen::Borderless(Some(monitor)))
@ -489,38 +482,38 @@ fn new_window(
// if decorations is set to false, ignore pl_attrs
//
// if the titlebar is hidden, ignore other pl_attrs
NSWindowStyleMask::Borderless.0
| NSWindowStyleMask::Resizable.0
| NSWindowStyleMask::Miniaturizable.0
NSWindowStyleMask::Borderless
| NSWindowStyleMask::Resizable
| NSWindowStyleMask::Miniaturizable
} else {
// default case, resizable window with titlebar and titlebar buttons
NSWindowStyleMask::Closable.0
| NSWindowStyleMask::Miniaturizable.0
| NSWindowStyleMask::Resizable.0
| NSWindowStyleMask::Titled.0
NSWindowStyleMask::Closable
| NSWindowStyleMask::Miniaturizable
| NSWindowStyleMask::Resizable
| NSWindowStyleMask::Titled
};
if !attrs.resizable {
masks &= !NSWindowStyleMask::Resizable.0;
masks &= !NSWindowStyleMask::Resizable;
}
if !attrs.enabled_buttons.contains(WindowButtons::MINIMIZE) {
masks &= !NSWindowStyleMask::Miniaturizable.0;
masks &= !NSWindowStyleMask::Miniaturizable;
}
if !attrs.enabled_buttons.contains(WindowButtons::CLOSE) {
masks &= !NSWindowStyleMask::Closable.0;
masks &= !NSWindowStyleMask::Closable;
}
if attrs.platform_specific.fullsize_content_view {
masks |= NSWindowStyleMask::FullSizeContentView.0;
masks |= NSWindowStyleMask::FullSizeContentView;
}
let window: Option<Id<WinitWindow>> = unsafe {
let window: Option<Retained<WinitWindow>> = unsafe {
msg_send_id![
super(mtm.alloc().set_ivars(())),
initWithContentRect: frame,
styleMask: NSWindowStyleMask(masks),
styleMask: masks,
backing: NSBackingStoreType::NSBackingStoreBuffered,
defer: false,
]
@ -625,7 +618,7 @@ impl WindowDelegate {
app_delegate: &ApplicationDelegate,
attrs: WindowAttributes,
mtm: MainThreadMarker,
) -> Result<Id<Self>, RootOsError> {
) -> Result<Retained<Self>, RootOsError> {
let window = new_window(app_delegate, &attrs, mtm)
.ok_or_else(|| os_error!(OsError::CreationError("couldn't create `NSWindow`")))?;
@ -634,8 +627,8 @@ impl WindowDelegate {
Some(rwh_06::RawWindowHandle::AppKit(handle)) => {
// SAFETY: Caller ensures the pointer is valid or NULL
// Unwrap is fine, since the pointer comes from `NonNull`.
let parent_view: Id<NSView> =
unsafe { Id::retain(handle.ns_view.as_ptr().cast()) }.unwrap();
let parent_view: Retained<NSView> =
unsafe { Retained::retain(handle.ns_view.as_ptr().cast()) }.unwrap();
let parent = parent_view.window().ok_or_else(|| {
os_error!(OsError::CreationError("parent view should be installed in a window"))
})?;
@ -685,7 +678,7 @@ impl WindowDelegate {
is_simple_fullscreen: Cell::new(false),
saved_style: Cell::new(None),
});
let delegate: Id<WindowDelegate> = unsafe { msg_send_id![super(delegate), init] };
let delegate: Retained<WindowDelegate> = unsafe { msg_send_id![super(delegate), init] };
if scale_factor != 1.0 {
delegate.queue_static_scale_factor_changed_event();
@ -745,9 +738,9 @@ impl WindowDelegate {
}
#[track_caller]
pub(super) fn view(&self) -> Id<WinitView> {
pub(super) fn view(&self) -> Retained<WinitView> {
// SAFETY: The view inside WinitWindow is always `WinitView`
unsafe { Id::cast(self.window().contentView().unwrap()) }
unsafe { Retained::cast(self.window().contentView().unwrap()) }
}
#[track_caller]
@ -960,13 +953,13 @@ impl WindowDelegate {
self.ivars().resizable.set(resizable);
let fullscreen = self.ivars().fullscreen.borrow().is_some();
if !fullscreen {
let mut mask = self.window().styleMask().0;
let mut mask = self.window().styleMask();
if resizable {
mask |= NSWindowStyleMask::Resizable.0;
mask |= NSWindowStyleMask::Resizable;
} else {
mask &= !NSWindowStyleMask::Resizable.0;
mask &= !NSWindowStyleMask::Resizable;
}
self.set_style_mask(NSWindowStyleMask(mask));
self.set_style_mask(mask);
}
// Otherwise, we don't change the mask until we exit fullscreen.
}
@ -978,23 +971,23 @@ impl WindowDelegate {
#[inline]
pub fn set_enabled_buttons(&self, buttons: WindowButtons) {
let mut mask = self.window().styleMask().0;
let mut mask = self.window().styleMask();
if buttons.contains(WindowButtons::CLOSE) {
mask |= NSWindowStyleMask::Closable.0;
mask |= NSWindowStyleMask::Closable;
} else {
mask &= !NSWindowStyleMask::Closable.0;
mask &= !NSWindowStyleMask::Closable;
}
if buttons.contains(WindowButtons::MINIMIZE) {
mask |= NSWindowStyleMask::Miniaturizable.0;
mask |= NSWindowStyleMask::Miniaturizable;
} else {
mask &= !NSWindowStyleMask::Miniaturizable.0;
mask &= !NSWindowStyleMask::Miniaturizable;
}
// This must happen before the button's "enabled" status has been set,
// hence we do it synchronously.
self.set_style_mask(NSWindowStyleMask(mask));
self.set_style_mask(mask);
// We edit the button directly instead of using `NSResizableWindowMask`,
// since that mask also affect the resizability of the window (which is
@ -1115,9 +1108,8 @@ impl WindowDelegate {
// we make it resizable temporarily.
let curr_mask = self.window().styleMask();
let required =
NSWindowStyleMask(NSWindowStyleMask::Titled.0 | NSWindowStyleMask::Resizable.0);
let needs_temp_mask = !mask_contains(curr_mask, required);
let required = NSWindowStyleMask::Titled | NSWindowStyleMask::Resizable;
let needs_temp_mask = !curr_mask.contains(required);
if needs_temp_mask {
self.set_style_mask(required);
}
@ -1134,12 +1126,12 @@ impl WindowDelegate {
fn saved_style(&self) -> NSWindowStyleMask {
let base_mask =
self.ivars().saved_style.take().unwrap_or_else(|| self.window().styleMask()).0;
NSWindowStyleMask(if self.ivars().resizable.get() {
base_mask | NSWindowStyleMask::Resizable.0
self.ivars().saved_style.take().unwrap_or_else(|| self.window().styleMask());
if self.ivars().resizable.get() {
base_mask | NSWindowStyleMask::Resizable
} else {
base_mask & !NSWindowStyleMask::Resizable.0
})
base_mask & !NSWindowStyleMask::Resizable
}
}
/// This is called when the window is exiting fullscreen, whether by the
@ -1194,7 +1186,7 @@ impl WindowDelegate {
return;
}
if mask_contains(self.window().styleMask(), NSWindowStyleMask::Resizable) {
if self.window().styleMask().contains(NSWindowStyleMask::Resizable) {
// Just use the native zoom if resizable
self.window().zoom(None);
} else {
@ -1346,9 +1338,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 =
NSWindowStyleMask(NSWindowStyleMask::Titled.0 | NSWindowStyleMask::Resizable.0);
if !mask_contains(curr_mask, required) {
let required = NSWindowStyleMask::Titled | NSWindowStyleMask::Resizable;
if !curr_mask.contains(required) {
self.set_style_mask(required);
self.ivars().saved_style.set(Some(curr_mask));
}
@ -1379,11 +1370,10 @@ impl WindowDelegate {
// delegate in `window:willUseFullScreenPresentationOptions:`.
self.ivars().save_presentation_opts.set(Some(app.presentationOptions()));
let presentation_options = NSApplicationPresentationOptions(
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar.0,
);
let presentation_options =
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar;
app.setPresentationOptions(presentation_options);
let window_level = unsafe { ffi::CGShieldingWindowLevel() } as NSWindowLevel + 1;
@ -1391,9 +1381,9 @@ impl WindowDelegate {
},
(Some(Fullscreen::Exclusive(ref video_mode)), Some(Fullscreen::Borderless(_))) => {
let presentation_options = self.ivars().save_presentation_opts.get().unwrap_or(
NSApplicationPresentationOptions(NSApplicationPresentationOptions::NSApplicationPresentationFullScreen.0
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar.0),
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar
);
app.setPresentationOptions(presentation_options);
@ -1432,19 +1422,19 @@ impl WindowDelegate {
let new_mask = {
let mut new_mask = if decorations {
NSWindowStyleMask::Closable.0
| NSWindowStyleMask::Miniaturizable.0
| NSWindowStyleMask::Resizable.0
| NSWindowStyleMask::Titled.0
NSWindowStyleMask::Closable
| NSWindowStyleMask::Miniaturizable
| NSWindowStyleMask::Resizable
| NSWindowStyleMask::Titled
} else {
NSWindowStyleMask::Borderless.0 | NSWindowStyleMask::Resizable.0
NSWindowStyleMask::Borderless | NSWindowStyleMask::Resizable
};
if !resizable {
new_mask &= !NSWindowStyleMask::Resizable.0;
new_mask &= !NSWindowStyleMask::Resizable;
}
new_mask
};
self.set_style_mask(NSWindowStyleMask(new_mask));
self.set_style_mask(new_mask);
}
#[inline]
@ -1547,7 +1537,7 @@ impl WindowDelegate {
pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle {
let mut window_handle = rwh_04::AppKitHandle::empty();
window_handle.ns_window = self.window() as *const WinitWindow as *mut _;
window_handle.ns_view = Id::as_ptr(&self.contentView().unwrap()) as *mut _;
window_handle.ns_view = Retained::as_ptr(&self.contentView().unwrap()) as *mut _;
rwh_04::RawWindowHandle::AppKit(window_handle)
}
@ -1556,7 +1546,7 @@ impl WindowDelegate {
pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle {
let mut window_handle = rwh_05::AppKitWindowHandle::empty();
window_handle.ns_window = self.window() as *const WinitWindow as *mut _;
window_handle.ns_view = Id::as_ptr(&self.view()) as *mut _;
window_handle.ns_view = Retained::as_ptr(&self.view()) as *mut _;
rwh_05::RawWindowHandle::AppKit(window_handle)
}
@ -1570,8 +1560,8 @@ impl WindowDelegate {
#[inline]
pub fn raw_window_handle_rwh_06(&self) -> rwh_06::RawWindowHandle {
let window_handle = rwh_06::AppKitWindowHandle::new({
let ptr = Id::as_ptr(&self.view()) as *mut _;
std::ptr::NonNull::new(ptr).expect("Id<T> should never be null")
let ptr = Retained::as_ptr(&self.view()) as *mut _;
std::ptr::NonNull::new(ptr).expect("Retained<T> should never be null")
});
rwh_06::RawWindowHandle::AppKit(window_handle)
}
@ -1579,9 +1569,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(NSWindowStyleMask(current_style_mask.0 | mask.0));
self.set_style_mask(current_style_mask | mask);
} else {
self.set_style_mask(NSWindowStyleMask(current_style_mask.0 & (!mask.0)));
self.set_style_mask(current_style_mask & !mask);
}
}
@ -1654,10 +1644,9 @@ 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 = NSApplicationPresentationOptions(
NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock.0
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar.0,
);
let presentation_options =
NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar;
app.setPresentationOptions(presentation_options);
// Hide the titlebar
@ -1755,10 +1744,6 @@ impl WindowExtMacOS for WindowDelegate {
}
}
fn mask_contains(mask: NSWindowStyleMask, value: NSWindowStyleMask) -> bool {
mask.0 & value.0 == value.0
}
const DEFAULT_STANDARD_FRAME: NSRect =
NSRect::new(NSPoint::new(50.0, 50.0), NSSize::new(800.0, 600.0));