From 836e7170219b69e818e03b503098291915c2438a 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/macos/cursor.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 4c9b9aa80..f3fc96849 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -62,3 +62,4 @@ changelog entry. - On X11, fix XInput handling that prevented a new window from getting the focus in some cases. - 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/macos/cursor.rs b/src/platform_impl/macos/cursor.rs index cc8f5f308..9e14e8be6 100644 --- a/src/platform_impl/macos/cursor.rs +++ b/src/platform_impl/macos/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, @@ -66,7 +66,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 {