From 5835c9102ec4621af92677aabd711e47fed1fbfd Mon Sep 17 00:00:00 2001 From: "Skip R." Date: Sun, 8 Dec 2024 13:01:57 -0800 Subject: [PATCH] macOS: Fix checking for undocumented cursors (#4033) `AnyClass::responds_to` delegates to `class_respondsToSelector`, a function provided by the Objective-C runtime. However, at some point, this began to return `false` for selectors referring to undocumented cursors, despite the cursors remaining accessible via said selectors. That this check fails prevents the cursors from being used. We can instead send `respondsToSelector:` to the `NSCursor` class itself. As an instance method, this is nominally impossible; however, Apple grants an exemption[1] that permits class objects to perform instance methods defined in the root class. Checking for the undocumented cursors in this way gets them working again, at least on macOS Sequoia 15.1.1. [1]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-TPXREF120 --- src/changelog/unreleased.md | 1 + src/platform_impl/apple/appkit/cursor.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 81d48512..340b5cef 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -216,3 +216,4 @@ changelog entry. - On macOS, fixed redundant `SurfaceResized` event at window creation. - On macOS, fix crash when pressing Caps Lock in certain configurations. - On iOS, fixed `MonitorHandle`'s `PartialEq` and `Hash` implementations. +- On macOS, fixed undocumented cursors (e.g. zoom, resize, help) always appearing to be invalid and falling back to the default cursor. diff --git a/src/platform_impl/apple/appkit/cursor.rs b/src/platform_impl/apple/appkit/cursor.rs index 70a36e11..b8befe11 100644 --- a/src/platform_impl/apple/appkit/cursor.rs +++ b/src/platform_impl/apple/appkit/cursor.rs @@ -4,7 +4,7 @@ use std::sync::OnceLock; use objc2::rc::Retained; use objc2::runtime::Sel; -use objc2::{msg_send_id, sel, ClassType}; +use objc2::{msg_send, msg_send_id, sel, ClassType}; use objc2_app_kit::{NSBitmapImageRep, NSCursor, NSDeviceRGBColorSpace, NSImage}; use objc2_foundation::{ ns_string, NSData, NSDictionary, NSNumber, NSObject, NSObjectProtocol, NSPoint, NSSize, @@ -67,7 +67,7 @@ pub(crate) fn default_cursor() -> Retained { unsafe fn try_cursor_from_selector(sel: Sel) -> Option> { let cls = NSCursor::class(); - if cls.responds_to(sel) { + if msg_send![cls, respondsToSelector: sel] { let cursor: Retained = unsafe { msg_send_id![cls, performSelector: sel] }; Some(cursor) } else {