Skip to content

Commit

Permalink
macOS: Fix selector response checking for undocumented cursors
Browse files Browse the repository at this point in the history
`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.

[1]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-TPXREF120

Checking for the undocumented cursors in this way gets them working
again, at least on macOS Sequoia 15.1.1.
  • Loading branch information
slice committed Dec 8, 2024
1 parent e47081e commit 9b60765
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 2 additions & 2 deletions src/platform_impl/apple/appkit/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -67,7 +67,7 @@ pub(crate) fn default_cursor() -> Retained<NSCursor> {

unsafe fn try_cursor_from_selector(sel: Sel) -> Option<Retained<NSCursor>> {
let cls = NSCursor::class();
if cls.responds_to(sel) {
if msg_send![cls, respondsToSelector: sel] {
let cursor: Retained<NSCursor> = unsafe { msg_send_id![cls, performSelector: sel] };
Some(cursor)
} else {
Expand Down

0 comments on commit 9b60765

Please sign in to comment.