Skip to content

Commit afd72f2

Browse files
committed
added mouse cursor support to macos via macos/window
1 parent 6e2087f commit afd72f2

4 files changed

Lines changed: 99 additions & 1 deletion

File tree

src/macos/cursor.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use cocoa::base::id;
2+
use objc::{runtime::Sel, msg_send, sel, sel_impl, class};
3+
4+
use crate::MouseCursor;
5+
6+
#[derive(Debug)]
7+
pub enum Cursor {
8+
Native(&'static str),
9+
Undocumented(&'static str),
10+
}
11+
12+
impl From<MouseCursor> for Cursor {
13+
fn from(cursor: MouseCursor) -> Self {
14+
match cursor {
15+
MouseCursor::Default => Cursor::Native("arrowCursor"),
16+
MouseCursor::Pointer => Cursor::Native("pointingHandCursor"),
17+
MouseCursor::Hand => Cursor::Native("openHandCursor"),
18+
MouseCursor::HandGrabbing => Cursor::Native("closedHandCursor"),
19+
MouseCursor::Text => Cursor::Native("IBeamCursor"),
20+
MouseCursor::VerticalText => Cursor::Native("IBeamCursorForVerticalLayout"),
21+
MouseCursor::Copy => Cursor::Native("dragCopyCursor"),
22+
MouseCursor::Alias => Cursor::Native("dragLinkCursor"),
23+
MouseCursor::NotAllowed | MouseCursor::PtrNotAllowed => {
24+
Cursor::Native("operationNotAllowedCursor")
25+
}
26+
// MouseCursor:: => Cursor::Native("contextualMenuCursor"),
27+
MouseCursor::Crosshair => Cursor::Native("crosshairCursor"),
28+
MouseCursor::EResize => Cursor::Native("resizeRightCursor"),
29+
MouseCursor::NResize => Cursor::Native("resizeUpCursor"),
30+
MouseCursor::WResize => Cursor::Native("resizeLeftCursor"),
31+
MouseCursor::SResize => Cursor::Native("resizeDownCursor"),
32+
MouseCursor::EwResize | MouseCursor::ColResize => Cursor::Native("resizeLeftRightCursor"),
33+
MouseCursor::NsResize | MouseCursor::RowResize => Cursor::Native("resizeUpDownCursor"),
34+
35+
MouseCursor::Help => Cursor::Undocumented("_helpCursor"),
36+
MouseCursor::ZoomIn => Cursor::Undocumented("_zoomInCursor"),
37+
MouseCursor::ZoomOut => Cursor::Undocumented("_zoomOutCursor"),
38+
MouseCursor::NeResize => Cursor::Undocumented("_windowResizeNorthEastCursor"),
39+
MouseCursor::NwResize => Cursor::Undocumented("_windowResizeNorthWestCursor"),
40+
MouseCursor::SeResize => Cursor::Undocumented("_windowResizeSouthEastCursor"),
41+
MouseCursor::SwResize => Cursor::Undocumented("_windowResizeSouthWestCursor"),
42+
MouseCursor::NeswResize => Cursor::Undocumented("_windowResizeNorthEastSouthWestCursor"),
43+
MouseCursor::NwseResize => Cursor::Undocumented("_windowResizeNorthWestSouthEastCursor"),
44+
45+
MouseCursor::Working | MouseCursor::PtrWorking => {
46+
Cursor::Undocumented("busyButClickableCursor")
47+
}
48+
49+
_ => Cursor::Native("arrowCursor"),
50+
51+
// MouseCursor::Hidden => todo!(),
52+
// MouseCursor::Move => todo!(),
53+
// MouseCursor::AllScroll => todo!(),
54+
// MouseCursor::Cell => todo!(),
55+
}
56+
}
57+
}
58+
59+
impl Cursor {
60+
pub unsafe fn load(&self) -> id {
61+
match self {
62+
Cursor::Native(cursor_name) => {
63+
let sel = Sel::register(cursor_name);
64+
msg_send![class!(NSCursor), performSelector: sel]
65+
}
66+
Cursor::Undocumented(cursor_name) => {
67+
let class = class!(NSCursor);
68+
let sel = Sel::register(cursor_name);
69+
let sel = if msg_send![class, respondsToSelector: sel] {
70+
sel
71+
} else {
72+
sel!(arrowCursor)
73+
};
74+
msg_send![class, performSelector: sel]
75+
}
76+
}
77+
}
78+
}

src/macos/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod keyboard;
22
mod view;
33
mod window;
4+
mod cursor;
45

56
pub use window::*;

src/macos/window.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
2020
use raw_window_handle::{AppKitHandle, HasRawWindowHandle, RawWindowHandle};
2121

2222
use crate::{
23-
Event, EventStatus, Size, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions,
23+
Event, EventStatus, Size, MouseCursor, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions,
2424
WindowScalePolicy,
2525
};
2626

27+
use super::cursor::Cursor;
2728
use super::keyboard::KeyboardState;
2829
use super::view::{create_view, BASEVIEW_STATE_IVAR};
2930

@@ -338,6 +339,18 @@ impl Window {
338339
}
339340
}
340341

342+
pub fn set_mouse_cursor(&self, cursor: MouseCursor) {
343+
let native_cursor = Cursor::from(cursor);
344+
unsafe {
345+
let bounds: NSRect = msg_send![self.ns_view as id, bounds];
346+
let cursor = native_cursor.load();
347+
let _: () = msg_send![self.ns_view as id,
348+
addCursorRect:bounds
349+
cursor:cursor
350+
];
351+
}
352+
}
353+
341354
#[cfg(feature = "opengl")]
342355
pub fn gl_context(&self) -> Option<&GlContext> {
343356
self.gl_context.as_ref()

src/window.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
55
use crate::event::{Event, EventStatus};
66
use crate::window_open_options::WindowOpenOptions;
77
use crate::Size;
8+
use crate::MouseCursor;
89

910
#[cfg(target_os = "macos")]
1011
use crate::macos as platform;
@@ -114,6 +115,11 @@ impl<'a> Window<'a> {
114115
pub fn resize(&mut self, size: Size) {
115116
self.window.resize(size);
116117
}
118+
119+
/// Set the cursor to the given cursor type
120+
pub fn set_mouse_cursor(&self, cursor: MouseCursor) {
121+
self.window.set_mouse_cursor(cursor);
122+
}
117123

118124
/// If provided, then an OpenGL context will be created for this window. You'll be able to
119125
/// access this context through [crate::Window::gl_context].

0 commit comments

Comments
 (0)