Skip to content

Commit 3fb9adc

Browse files
SpruceCloudPepik Malej
authored andcommitted
Implement macOS cursor setting and hiding support
1 parent 91e3b4a commit 3fb9adc

3 files changed

Lines changed: 34 additions & 12 deletions

File tree

src/platform/macos/cursor.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::MouseCursor;
99
pub enum Cursor {
1010
Native(fn() -> Retained<NSCursor>),
1111
Undocumented(Sel),
12+
Hidden,
1213
}
1314

1415
impl From<MouseCursor> for Cursor {
@@ -60,34 +61,34 @@ impl From<MouseCursor> for Cursor {
6061
Cursor::Undocumented(sel!(busyButClickableCursor))
6162
}
6263

63-
_ => Cursor::Native(NSCursor::arrowCursor),
64-
// MouseCursor::Hidden => todo!(),
65-
// MouseCursor::Move => todo!(),
66-
// MouseCursor::AllScroll => todo!(),
67-
// MouseCursor::Cell => todo!(),
64+
MouseCursor::Move => Cursor::Native(NSCursor::arrowCursor),
65+
MouseCursor::AllScroll => Cursor::Native(NSCursor::arrowCursor),
66+
MouseCursor::Cell => Cursor::Native(NSCursor::crosshairCursor),
67+
MouseCursor::Hidden => Cursor::Hidden,
6868
}
6969
}
7070
}
7171

7272
impl Cursor {
73-
pub fn load(&self) -> Retained<NSCursor> {
73+
pub fn load(&self) -> Option<Retained<NSCursor>> {
7474
match self {
75-
Cursor::Native(loader) => loader(),
75+
Cursor::Native(loader) => Some(loader()),
7676
Cursor::Undocumented(sel) => {
7777
let class = NSCursor::class();
7878

7979
// NOTE: class.responds_to does not yield the same result (probably because NSCursor overrides respondsToSelector)
8080
let responds_to: bool = unsafe { msg_send![class, respondsToSelector: *sel] };
8181

8282
if !responds_to {
83-
return NSCursor::arrowCursor();
83+
return Some(NSCursor::arrowCursor());
8484
}
8585

8686
let raw: *mut NSCursor = unsafe { class.send_message(*sel, ()) };
8787
let cursor = unsafe { Retained::retain(raw) };
8888

89-
cursor.unwrap_or_else(NSCursor::arrowCursor)
89+
Some(cursor.unwrap_or_else(NSCursor::arrowCursor))
9090
}
91+
Cursor::Hidden => None,
9192
}
9293
}
9394
}

src/platform/macos/view.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
use objc2::__framework_prelude::Retained;
1212
use objc2::rc::Weak;
1313
use objc2::runtime::{NSObjectProtocol, ProtocolObject};
14-
use objc2::{msg_send, AllocAnyThread};
14+
use objc2::{msg_send, AllocAnyThread, ClassType};
1515
use objc2_app_kit::{
1616
NSApplication, NSDragOperation, NSDraggingInfo, NSEvent, NSFilenamesPboardType, NSTrackingArea,
1717
NSTrackingAreaOptions, NSView, NSWindow,
@@ -230,6 +230,11 @@ impl BaseviewView {
230230
impl Drop for BaseviewView {
231231
fn drop(&mut self) {
232232
self.state.closed.set(true);
233+
if self.state.cursor_hidden.get() {
234+
unsafe {
235+
let _: () = objc2::msg_send![objc2_app_kit::NSCursor::class(), unhide];
236+
}
237+
}
233238
}
234239
}
235240

src/platform/macos/window.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::rc::Rc;
33

44
use objc2::rc::{autoreleasepool, Weak};
55
use objc2::runtime::NSObjectProtocol;
6-
use objc2::MainThreadMarker;
6+
use objc2::{ClassType, MainThreadMarker};
77
use objc2_app_kit::{
88
NSApplication, NSApplicationActivationPolicy, NSPasteboard, NSPasteboardTypeString,
99
};
@@ -156,7 +156,21 @@ impl<'a> Window<'a> {
156156

157157
pub fn set_mouse_cursor(&self, cursor: MouseCursor) {
158158
let native_cursor = Cursor::from(cursor);
159-
self.view.addCursorRect_cursor(self.view.bounds(), &native_cursor.load());
159+
unsafe {
160+
if let Some(loaded_cursor) = native_cursor.load() {
161+
if self.inner.state.cursor_hidden.get() {
162+
let _: () = objc2::msg_send![objc2_app_kit::NSCursor::class(), unhide];
163+
self.inner.state.cursor_hidden.set(false);
164+
}
165+
let _: () = objc2::msg_send![&loaded_cursor, set];
166+
self.view.addCursorRect_cursor(self.view.bounds(), &loaded_cursor);
167+
} else {
168+
if !self.inner.state.cursor_hidden.get() {
169+
let _: () = objc2::msg_send![objc2_app_kit::NSCursor::class(), hide];
170+
self.inner.state.cursor_hidden.set(true);
171+
}
172+
}
173+
}
160174
}
161175

162176
#[cfg(feature = "opengl")]
@@ -169,13 +183,15 @@ pub(crate) struct WindowSharedState {
169183
/// The last known window info for this window.
170184
pub window_info: Cell<WindowInfo>,
171185
pub closed: Cell<bool>,
186+
pub cursor_hidden: Cell<bool>,
172187
}
173188

174189
impl WindowSharedState {
175190
pub fn new(options: &WindowOpenOptions) -> Self {
176191
Self {
177192
window_info: WindowInfo::from_logical_size(options.size, 1.0).into(),
178193
closed: false.into(),
194+
cursor_hidden: false.into(),
179195
}
180196
}
181197
}

0 commit comments

Comments
 (0)