From d5d202d60e8201c4f804ad600390198cce0fdb26 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 6 May 2024 17:09:38 +0200 Subject: [PATCH] Reduce usage of direct `msg_send!` --- Cargo.toml | 5 +- src/platform_impl/ios/app_state.rs | 31 +++++------ src/platform_impl/ios/window.rs | 12 ++--- src/platform_impl/macos/view.rs | 37 +++++-------- src/platform_impl/macos/window_delegate.rs | 62 +++++++++------------- 5 files changed, 61 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d1645b2..e858087e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,11 +121,14 @@ features = [ "NSAttributedString", "NSData", "NSDictionary", + "NSDistributedNotificationCenter", "NSEnumerator", + "NSNotification", "NSObjCRuntime", - "NSString", "NSPathUtilities", "NSProcessInfo", + "NSRunLoop", + "NSString", "NSThread", "NSValue", ] diff --git a/src/platform_impl/ios/app_state.rs b/src/platform_impl/ios/app_state.rs index 15dd25f3..d9c54c0e 100644 --- a/src/platform_impl/ios/app_state.rs +++ b/src/platform_impl/ios/app_state.rs @@ -17,7 +17,8 @@ use objc2::rc::Id; use objc2::runtime::AnyObject; use objc2::{msg_send, sel}; use objc2_foundation::{ - CGRect, CGSize, MainThreadMarker, NSInteger, NSOperatingSystemVersion, NSProcessInfo, + CGRect, CGSize, MainThreadMarker, NSInteger, NSObjectProtocol, NSOperatingSystemVersion, + NSProcessInfo, }; use super::uikit::UIView; @@ -857,23 +858,17 @@ fn meets_requirements( } fn get_version() -> NSOperatingSystemVersion { - unsafe { - let process_info = NSProcessInfo::processInfo(); - let atleast_ios_8: bool = msg_send![ - &process_info, - respondsToSelector: sel!(operatingSystemVersion) - ]; - // winit requires atleast iOS 8 because no one has put the time into supporting earlier os - // versions. Older iOS versions are increasingly difficult to test. For example, - // Xcode 11 does not support debugging on devices with an iOS version of less than - // 8. Another example, in order to use an iOS simulator older than iOS 8, you must - // download an older version of Xcode (<9), and at least Xcode 7 has been tested to - // not even run on macOS 10.15 - Xcode 8 might? - // - // The minimum required iOS version is likely to grow in the future. - assert!(atleast_ios_8, "`winit` requires iOS version 8 or greater"); - process_info.operatingSystemVersion() - } + let process_info = NSProcessInfo::processInfo(); + let atleast_ios_8 = process_info.respondsToSelector(sel!(operatingSystemVersion)); + // Winit requires atleast iOS 8 because no one has put the time into supporting earlier os + // versions. Older iOS versions are increasingly difficult to test. For example, Xcode 11 does + // not support debugging on devices with an iOS version of less than 8. Another example, in + // order to use an iOS simulator older than iOS 8, you must download an older version of Xcode + // (<9), and at least Xcode 7 has been tested to not even run on macOS 10.15 - Xcode 8 might? + // + // The minimum required iOS version is likely to grow in the future. + assert!(atleast_ios_8, "`winit` requires iOS version 8 or greater"); + process_info.operatingSystemVersion() } pub fn os_capabilities() -> OSCapabilities { diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 4a4f975c..f42eed37 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -5,7 +5,9 @@ use std::collections::VecDeque; use objc2::rc::Id; use objc2::runtime::{AnyObject, NSObject}; use objc2::{class, declare_class, msg_send, msg_send_id, mutability, ClassType, DeclaredClass}; -use objc2_foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, MainThreadMarker}; +use objc2_foundation::{ + CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, MainThreadMarker, NSObjectProtocol, +}; use tracing::{debug, warn}; use super::app_state::EventWrapper; @@ -505,12 +507,8 @@ impl Window { let view = WinitView::new(mtm, &window_attributes, frame); - let gl_or_metal_backed = unsafe { - let layer_class = WinitView::layerClass(); - let is_metal = msg_send![layer_class, isSubclassOfClass: class!(CAMetalLayer)]; - let is_gl = msg_send![layer_class, isSubclassOfClass: class!(CAEAGLLayer)]; - is_metal || is_gl - }; + let gl_or_metal_backed = + view.isKindOfClass(class!(CAMetalLayer)) || view.isKindOfClass(class!(CAEAGLLayer)); let view_controller = WinitViewController::new(mtm, &window_attributes, &view); let window = WinitUIWindow::new(mtm, &window_attributes, frame, &view_controller); diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 2166da7e..19d8ea53 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -5,17 +5,15 @@ use std::ptr; use objc2::rc::{Id, WeakId}; use objc2::runtime::{AnyObject, Sel}; -use objc2::{ - class, declare_class, msg_send, msg_send_id, mutability, sel, ClassType, DeclaredClass, -}; +use objc2::{declare_class, msg_send_id, mutability, sel, ClassType, DeclaredClass}; use objc2_app_kit::{ NSApplication, NSCursor, NSEvent, NSEventPhase, NSResponder, NSTextInputClient, - NSTrackingRectTag, NSView, + NSTrackingRectTag, NSView, NSViewFrameDidChangeNotification, }; use objc2_foundation::{ MainThreadMarker, NSArray, NSAttributedString, NSAttributedStringKey, NSCopying, - NSMutableAttributedString, NSNotFound, NSObject, NSObjectProtocol, NSPoint, NSRange, NSRect, - NSSize, NSString, NSUInteger, + NSMutableAttributedString, NSNotFound, NSNotificationCenter, NSObject, NSObjectProtocol, + NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger, }; use super::app_delegate::ApplicationDelegate; @@ -202,7 +200,7 @@ declare_class!( } #[method(drawRect:)] - fn draw_rect(&self, rect: NSRect) { + fn draw_rect(&self, _rect: NSRect) { trace_scope!("drawRect:"); // It's a workaround for https://github.com/rust-windowing/winit/issues/2640, don't replace with `self.window_id()`. @@ -210,10 +208,7 @@ declare_class!( self.ivars().app_delegate.handle_redraw(window.id()); } - #[allow(clippy::let_unit_value)] - unsafe { - let _: () = msg_send![super(self), drawRect: rect]; - } + // This is a direct subclass of NSView, no need to call superclass' drawRect: } #[method(acceptsFirstResponder)] @@ -803,20 +798,14 @@ impl WinitView { let this: Id = unsafe { msg_send_id![super(this), init] }; this.setPostsFrameChangedNotifications(true); - let notification_center: &AnyObject = - unsafe { msg_send![class!(NSNotificationCenter), defaultCenter] }; - // About frame change - let frame_did_change_notification_name = - NSString::from_str("NSViewFrameDidChangeNotification"); - #[allow(clippy::let_unit_value)] + let notification_center = unsafe { NSNotificationCenter::defaultCenter() }; unsafe { - let _: () = msg_send![ - notification_center, - addObserver: &*this, - selector: sel!(frameDidChange:), - name: &*frame_did_change_notification_name, - object: &*this, - ]; + notification_center.addObserver_selector_name_object( + &this, + sel!(frameDidChange:), + Some(NSViewFrameDidChangeNotification), + Some(&this), + ) } *this.ivars().input_source.borrow_mut() = this.current_input_source(); diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 4607ba26..02856107 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -1,15 +1,12 @@ #![allow(clippy::unnecessary_cast)] use std::cell::{Cell, RefCell}; use std::collections::VecDeque; -use std::ptr; use core_graphics::display::{CGDisplay, CGPoint}; 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::{declare_class, msg_send_id, mutability, sel, ClassType, DeclaredClass}; use objc2_app_kit::{ NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSApplication, NSApplicationPresentationOptions, NSBackingStoreType, NSDraggingDestination, @@ -19,8 +16,9 @@ use objc2_app_kit::{ NSWindowTabbingMode, NSWindowTitleVisibility, }; use objc2_foundation::{ - CGFloat, MainThreadMarker, NSArray, NSCopying, NSObject, NSObjectProtocol, NSPoint, NSRect, - NSSize, NSString, + ns_string, CGFloat, MainThreadMarker, NSArray, NSCopying, NSDistributedNotificationCenter, + NSObject, NSObjectNSDelayedPerforming, NSObjectNSThreadPerformAdditions, NSObjectProtocol, + NSPoint, NSRect, NSSize, NSString, }; use super::app_delegate::ApplicationDelegate; @@ -319,14 +317,12 @@ declare_class!( self.ivars().in_fullscreen_transition.set(false); self.ivars().target_fullscreen.replace(None); if self.ivars().initial_fullscreen.get() { - #[allow(clippy::let_unit_value)] unsafe { - let _: () = msg_send![ - self.window(), - performSelector: sel!(toggleFullScreen:), - withObject: ptr::null::(), - afterDelay: 0.5, - ]; + self.window().performSelector_withObject_afterDelay( + sel!(toggleFullScreen:), + None, + 0.5, + ) }; } else { self.restore_state_from_fullscreen(); @@ -421,16 +417,15 @@ declare_class!( unsafe impl WindowDelegate { // Observe theme change #[method(effectiveAppearanceDidChange:)] - fn effective_appearance_did_change(this: *mut Self, sender: Option<&AnyObject>) { + fn effective_appearance_did_change(&self, sender: Option<&AnyObject>) { trace_scope!("effectiveAppearanceDidChange:"); unsafe { - msg_send![ - this, - performSelectorOnMainThread: sel!(effectiveAppearanceDidChangedOnMainThread:), - withObject: sender, - waitUntilDone: false, - ] - } + self.performSelectorOnMainThread_withObject_waitUntilDone( + sel!(effectiveAppearanceDidChangedOnMainThread:), + sender, + false, + ) + }; } #[method(effectiveAppearanceDidChangedOnMainThread:)] @@ -698,17 +693,14 @@ impl WindowDelegate { window.setDelegate(Some(ProtocolObject::from_ref(&*delegate))); // Enable theme change event - let notification_center: Id = - unsafe { msg_send_id![class!(NSDistributedNotificationCenter), defaultCenter] }; - let notification_name = NSString::from_str("AppleInterfaceThemeChangedNotification"); - let _: () = unsafe { - msg_send![ - ¬ification_center, - addObserver: &*delegate, - selector: sel!(effectiveAppearanceDidChange:), - name: &*notification_name, - object: ptr::null::(), - ] + let notification_center = unsafe { NSDistributedNotificationCenter::defaultCenter() }; + unsafe { + notification_center.addObserver_selector_name_object( + &delegate, + sel!(effectiveAppearanceDidChange:), + Some(ns_string!("AppleInterfaceThemeChangedNotification")), + None, + ) }; if attrs.blur { @@ -1772,8 +1764,7 @@ const DEFAULT_STANDARD_FRAME: NSRect = pub(super) fn get_ns_theme(mtm: MainThreadMarker) -> Theme { let app = NSApplication::sharedApplication(mtm); - let has_theme: bool = unsafe { msg_send![&app, respondsToSelector: sel!(effectiveAppearance)] }; - if !has_theme { + if !app.respondsToSelector(sel!(effectiveAppearance)) { return Theme::Light; } let appearance = app.effectiveAppearance(); @@ -1791,8 +1782,7 @@ pub(super) fn get_ns_theme(mtm: MainThreadMarker) -> Theme { fn set_ns_theme(theme: Option, mtm: MainThreadMarker) { let app = NSApplication::sharedApplication(mtm); - let has_theme: bool = unsafe { msg_send![&app, respondsToSelector: sel!(effectiveAppearance)] }; - if has_theme { + if app.respondsToSelector(sel!(effectiveAppearance)) { let appearance = theme.map(|t| { let name = match t { Theme::Dark => NSString::from_str("NSAppearanceNameDarkAqua"),