diff --git a/Cargo.toml b/Cargo.toml index 54cbd5d5..0a271095 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,6 +76,7 @@ block2 = "0.6.2" objc2-foundation = { version = "0.3.2", default-features = false, features = ["std", "NSEnumerator", "block2", "NSOperation"] } objc2-app-kit = { version = "0.3.2", default-features = false, features = [ "NSApplication", + "NSCursor", "NSDragging", "NSEvent", "NSGraphics", diff --git a/src/macos/cursor.rs b/src/macos/cursor.rs new file mode 100644 index 00000000..27550134 --- /dev/null +++ b/src/macos/cursor.rs @@ -0,0 +1,93 @@ +use objc2::__framework_prelude::Retained; +use objc2::runtime::{MessageReceiver, Sel}; +use objc2::{msg_send, sel, ClassType}; +use objc2_app_kit::NSCursor; + +use crate::MouseCursor; + +#[derive(Debug)] +pub enum Cursor { + Native(fn() -> Retained), + Undocumented(Sel), +} + +impl From for Cursor { + fn from(cursor: MouseCursor) -> Self { + match cursor { + MouseCursor::Default => Cursor::Native(NSCursor::arrowCursor), + MouseCursor::Hand => Cursor::Native(NSCursor::openHandCursor), + MouseCursor::HandGrabbing => Cursor::Native(NSCursor::closedHandCursor), + MouseCursor::Text => Cursor::Native(NSCursor::IBeamCursor), + MouseCursor::VerticalText => Cursor::Native(NSCursor::IBeamCursorForVerticalLayout), + MouseCursor::Copy => Cursor::Native(NSCursor::dragCopyCursor), + MouseCursor::Alias => Cursor::Native(NSCursor::dragLinkCursor), + MouseCursor::NotAllowed | MouseCursor::PtrNotAllowed => { + Cursor::Native(NSCursor::operationNotAllowedCursor) + } + MouseCursor::Crosshair => Cursor::Native(NSCursor::crosshairCursor), + #[allow(deprecated)] + MouseCursor::EResize => Cursor::Native(NSCursor::resizeRightCursor), + #[allow(deprecated)] + MouseCursor::NResize => Cursor::Native(NSCursor::resizeUpCursor), + #[allow(deprecated)] + MouseCursor::WResize => Cursor::Native(NSCursor::resizeLeftCursor), + #[allow(deprecated)] + MouseCursor::SResize => Cursor::Native(NSCursor::resizeDownCursor), + #[allow(deprecated)] + MouseCursor::EwResize | MouseCursor::ColResize => { + Cursor::Native(NSCursor::resizeLeftRightCursor) + } + #[allow(deprecated)] + MouseCursor::NsResize | MouseCursor::RowResize => { + Cursor::Native(NSCursor::resizeUpDownCursor) + } + + MouseCursor::Help => Cursor::Undocumented(sel!(_helpCursor)), + MouseCursor::ZoomIn => Cursor::Undocumented(sel!(_zoomInCursor)), + MouseCursor::ZoomOut => Cursor::Undocumented(sel!(_zoomOutCursor)), + MouseCursor::NeResize => Cursor::Undocumented(sel!(_windowResizeNorthEastCursor)), + MouseCursor::NwResize => Cursor::Undocumented(sel!(_windowResizeNorthWestCursor)), + MouseCursor::SeResize => Cursor::Undocumented(sel!(_windowResizeSouthEastCursor)), + MouseCursor::SwResize => Cursor::Undocumented(sel!(_windowResizeSouthWestCursor)), + MouseCursor::NeswResize => { + Cursor::Undocumented(sel!(_windowResizeNorthEastSouthWestCursor)) + } + MouseCursor::NwseResize => { + Cursor::Undocumented(sel!(_windowResizeNorthWestSouthEastCursor)) + } + + MouseCursor::Working | MouseCursor::PtrWorking => { + Cursor::Undocumented(sel!(busyButClickableCursor)) + } + + _ => Cursor::Native(NSCursor::arrowCursor), + // MouseCursor::Hidden => todo!(), + // MouseCursor::Move => todo!(), + // MouseCursor::AllScroll => todo!(), + // MouseCursor::Cell => todo!(), + } + } +} + +impl Cursor { + pub fn load(&self) -> Retained { + match self { + Cursor::Native(loader) => loader(), + Cursor::Undocumented(sel) => { + let class = NSCursor::class(); + + // NOTE: class.responds_to does not yield the same result (probably because NSCursor overrides respondsToSelector) + let responds_to: bool = unsafe { msg_send![class, respondsToSelector: *sel] }; + + if !responds_to { + return NSCursor::arrowCursor(); + } + + let raw: *mut NSCursor = unsafe { class.send_message(*sel, ()) }; + let cursor = unsafe { Retained::from_raw(raw) }; + + cursor.unwrap_or_else(NSCursor::arrowCursor) + } + } + } +} diff --git a/src/macos/mod.rs b/src/macos/mod.rs index e1fa7b87..8b5a303b 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,3 +1,4 @@ +mod cursor; mod keyboard; mod view; mod window; diff --git a/src/macos/window.rs b/src/macos/window.rs index a3d5f9b5..f56a0f74 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -13,6 +13,7 @@ use raw_window_handle::{ RawDisplayHandle, RawWindowHandle, }; +use super::cursor::Cursor; use crate::{MouseCursor, Size, WindowHandler, WindowInfo, WindowOpenOptions}; #[cfg(feature = "opengl")] @@ -153,8 +154,9 @@ impl<'a> Window<'a> { BaseviewView::resize(self.view.inner_ref(), size); } - pub fn set_mouse_cursor(&mut self, _mouse_cursor: MouseCursor) { - todo!() + pub fn set_mouse_cursor(&self, cursor: MouseCursor) { + let native_cursor = Cursor::from(cursor); + self.view.addCursorRect_cursor(self.view.bounds(), &native_cursor.load()); } #[cfg(feature = "opengl")]