Skip to content

Commit

Permalink
Reduce usage of direct msg_send!
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed May 6, 2024
1 parent cb39ab2 commit d5d202d
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 86 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,14 @@ features = [
"NSAttributedString",
"NSData",
"NSDictionary",
"NSDistributedNotificationCenter",
"NSEnumerator",
"NSNotification",
"NSObjCRuntime",
"NSString",
"NSPathUtilities",
"NSProcessInfo",
"NSRunLoop",
"NSString",
"NSThread",
"NSValue",
]
Expand Down
31 changes: 13 additions & 18 deletions src/platform_impl/ios/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 5 additions & 7 deletions src/platform_impl/ios/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
37 changes: 13 additions & 24 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -202,18 +200,15 @@ 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()`.
if let Some(window) = self.ivars()._ns_window.load() {
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)]
Expand Down Expand Up @@ -803,20 +798,14 @@ impl WinitView {
let this: Id<Self> = 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();
Expand Down
62 changes: 26 additions & 36 deletions src/platform_impl/macos/window_delegate.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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::<AnyObject>(),
afterDelay: 0.5,
];
self.window().performSelector_withObject_afterDelay(
sel!(toggleFullScreen:),
None,
0.5,
)
};
} else {
self.restore_state_from_fullscreen();
Expand Down Expand Up @@ -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:)]
Expand Down Expand Up @@ -698,17 +693,14 @@ impl WindowDelegate {
window.setDelegate(Some(ProtocolObject::from_ref(&*delegate)));

// Enable theme change event
let notification_center: Id<AnyObject> =
unsafe { msg_send_id![class!(NSDistributedNotificationCenter), defaultCenter] };
let notification_name = NSString::from_str("AppleInterfaceThemeChangedNotification");
let _: () = unsafe {
msg_send![
&notification_center,
addObserver: &*delegate,
selector: sel!(effectiveAppearanceDidChange:),
name: &*notification_name,
object: ptr::null::<AnyObject>(),
]
let notification_center = unsafe { NSDistributedNotificationCenter::defaultCenter() };
unsafe {
notification_center.addObserver_selector_name_object(
&delegate,
sel!(effectiveAppearanceDidChange:),
Some(ns_string!("AppleInterfaceThemeChangedNotification")),
None,
)
};

if attrs.blur {
Expand Down Expand Up @@ -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();
Expand All @@ -1791,8 +1782,7 @@ pub(super) fn get_ns_theme(mtm: MainThreadMarker) -> Theme {

fn set_ns_theme(theme: Option<Theme>, 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"),
Expand Down

0 comments on commit d5d202d

Please sign in to comment.