From 6e2087f2482e970b62b4c6ffd40530c1b463dd4b Mon Sep 17 00:00:00 2001 From: aymeric Date: Wed, 14 Sep 2022 08:47:31 +0300 Subject: [PATCH 01/13] added Pointer to the cursors --- src/mouse_cursor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mouse_cursor.rs b/src/mouse_cursor.rs index 16fc199d..4abfbf19 100644 --- a/src/mouse_cursor.rs +++ b/src/mouse_cursor.rs @@ -3,6 +3,7 @@ pub enum MouseCursor { Default, Hand, HandGrabbing, + Pointer, Help, Hidden, From afd72f2d9a7f31f059399e2148bb8358fa192e4d Mon Sep 17 00:00:00 2001 From: aymeric Date: Wed, 14 Sep 2022 08:48:16 +0300 Subject: [PATCH 02/13] added mouse cursor support to macos via macos/window --- src/macos/cursor.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++ src/macos/mod.rs | 1 + src/macos/window.rs | 15 ++++++++- src/window.rs | 6 ++++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/macos/cursor.rs diff --git a/src/macos/cursor.rs b/src/macos/cursor.rs new file mode 100644 index 00000000..17846cce --- /dev/null +++ b/src/macos/cursor.rs @@ -0,0 +1,78 @@ +use cocoa::base::id; +use objc::{runtime::Sel, msg_send, sel, sel_impl, class}; + +use crate::MouseCursor; + +#[derive(Debug)] +pub enum Cursor { + Native(&'static str), + Undocumented(&'static str), +} + +impl From for Cursor { + fn from(cursor: MouseCursor) -> Self { + match cursor { + MouseCursor::Default => Cursor::Native("arrowCursor"), + MouseCursor::Pointer => Cursor::Native("pointingHandCursor"), + MouseCursor::Hand => Cursor::Native("openHandCursor"), + MouseCursor::HandGrabbing => Cursor::Native("closedHandCursor"), + MouseCursor::Text => Cursor::Native("IBeamCursor"), + MouseCursor::VerticalText => Cursor::Native("IBeamCursorForVerticalLayout"), + MouseCursor::Copy => Cursor::Native("dragCopyCursor"), + MouseCursor::Alias => Cursor::Native("dragLinkCursor"), + MouseCursor::NotAllowed | MouseCursor::PtrNotAllowed => { + Cursor::Native("operationNotAllowedCursor") + } + // MouseCursor:: => Cursor::Native("contextualMenuCursor"), + MouseCursor::Crosshair => Cursor::Native("crosshairCursor"), + MouseCursor::EResize => Cursor::Native("resizeRightCursor"), + MouseCursor::NResize => Cursor::Native("resizeUpCursor"), + MouseCursor::WResize => Cursor::Native("resizeLeftCursor"), + MouseCursor::SResize => Cursor::Native("resizeDownCursor"), + MouseCursor::EwResize | MouseCursor::ColResize => Cursor::Native("resizeLeftRightCursor"), + MouseCursor::NsResize | MouseCursor::RowResize => Cursor::Native("resizeUpDownCursor"), + + MouseCursor::Help => Cursor::Undocumented("_helpCursor"), + MouseCursor::ZoomIn => Cursor::Undocumented("_zoomInCursor"), + MouseCursor::ZoomOut => Cursor::Undocumented("_zoomOutCursor"), + MouseCursor::NeResize => Cursor::Undocumented("_windowResizeNorthEastCursor"), + MouseCursor::NwResize => Cursor::Undocumented("_windowResizeNorthWestCursor"), + MouseCursor::SeResize => Cursor::Undocumented("_windowResizeSouthEastCursor"), + MouseCursor::SwResize => Cursor::Undocumented("_windowResizeSouthWestCursor"), + MouseCursor::NeswResize => Cursor::Undocumented("_windowResizeNorthEastSouthWestCursor"), + MouseCursor::NwseResize => Cursor::Undocumented("_windowResizeNorthWestSouthEastCursor"), + + MouseCursor::Working | MouseCursor::PtrWorking => { + Cursor::Undocumented("busyButClickableCursor") + } + + _ => Cursor::Native("arrowCursor"), + + // MouseCursor::Hidden => todo!(), + // MouseCursor::Move => todo!(), + // MouseCursor::AllScroll => todo!(), + // MouseCursor::Cell => todo!(), + } + } +} + +impl Cursor { + pub unsafe fn load(&self) -> id { + match self { + Cursor::Native(cursor_name) => { + let sel = Sel::register(cursor_name); + msg_send![class!(NSCursor), performSelector: sel] + } + Cursor::Undocumented(cursor_name) => { + let class = class!(NSCursor); + let sel = Sel::register(cursor_name); + let sel = if msg_send![class, respondsToSelector: sel] { + sel + } else { + sel!(arrowCursor) + }; + msg_send![class, performSelector: sel] + } + } + } +} \ No newline at end of file diff --git a/src/macos/mod.rs b/src/macos/mod.rs index e1fa7b87..ef4ee2bc 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,5 +1,6 @@ mod keyboard; mod view; mod window; +mod cursor; pub use window::*; diff --git a/src/macos/window.rs b/src/macos/window.rs index 54046ddd..e6f9ea90 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -20,10 +20,11 @@ use objc::{msg_send, runtime::Object, sel, sel_impl}; use raw_window_handle::{AppKitHandle, HasRawWindowHandle, RawWindowHandle}; use crate::{ - Event, EventStatus, Size, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, + Event, EventStatus, Size, MouseCursor, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, }; +use super::cursor::Cursor; use super::keyboard::KeyboardState; use super::view::{create_view, BASEVIEW_STATE_IVAR}; @@ -338,6 +339,18 @@ impl Window { } } + pub fn set_mouse_cursor(&self, cursor: MouseCursor) { + let native_cursor = Cursor::from(cursor); + unsafe { + let bounds: NSRect = msg_send![self.ns_view as id, bounds]; + let cursor = native_cursor.load(); + let _: () = msg_send![self.ns_view as id, + addCursorRect:bounds + cursor:cursor + ]; + } + } + #[cfg(feature = "opengl")] pub fn gl_context(&self) -> Option<&GlContext> { self.gl_context.as_ref() diff --git a/src/window.rs b/src/window.rs index c0ef1ac8..8bbbb9da 100644 --- a/src/window.rs +++ b/src/window.rs @@ -5,6 +5,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use crate::event::{Event, EventStatus}; use crate::window_open_options::WindowOpenOptions; use crate::Size; +use crate::MouseCursor; #[cfg(target_os = "macos")] use crate::macos as platform; @@ -114,6 +115,11 @@ impl<'a> Window<'a> { pub fn resize(&mut self, size: Size) { self.window.resize(size); } + + /// Set the cursor to the given cursor type + pub fn set_mouse_cursor(&self, cursor: MouseCursor) { + self.window.set_mouse_cursor(cursor); + } /// If provided, then an OpenGL context will be created for this window. You'll be able to /// access this context through [crate::Window::gl_context]. From 4fb764ba2519ec7d2886e47ab09da4d9051f1558 Mon Sep 17 00:00:00 2001 From: aymeric Date: Wed, 14 Sep 2022 09:00:38 +0300 Subject: [PATCH 03/13] added Windows set_mouse_cursor stub --- src/win/window.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/win/window.rs b/src/win/window.rs index 2c68b99c..fe41efd6 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -760,6 +760,10 @@ impl Window<'_> { } } + pub fn set_mouse_cursor(&self, cursor: MouseCursor) { + //@TODO: Implement + } + pub fn close(&mut self) { unsafe { PostMessageW(self.state.hwnd, BV_WINDOW_MUST_CLOSE, 0, 0); From 8c6bf04187faa52b7bf3bd59454892c2b462dad7 Mon Sep 17 00:00:00 2001 From: aymeric Date: Wed, 14 Sep 2022 09:17:14 +0300 Subject: [PATCH 04/13] set_mouse_cursor self set to mut to follow the x11 impl --- src/win/window.rs | 2 +- src/window.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index fe41efd6..3b21be34 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -760,7 +760,7 @@ impl Window<'_> { } } - pub fn set_mouse_cursor(&self, cursor: MouseCursor) { + pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { //@TODO: Implement } diff --git a/src/window.rs b/src/window.rs index 8bbbb9da..1b6b704d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -117,7 +117,7 @@ impl<'a> Window<'a> { } /// Set the cursor to the given cursor type - pub fn set_mouse_cursor(&self, cursor: MouseCursor) { + pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { self.window.set_mouse_cursor(cursor); } From 21345380a7c0f91a3bf1aa72e7ee3d7ed909635b Mon Sep 17 00:00:00 2001 From: NunjaLinux Date: Wed, 14 Sep 2022 09:35:37 +0300 Subject: [PATCH 05/13] added case for MouseCursor::Pointer --- src/x11/cursor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x11/cursor.rs b/src/x11/cursor.rs index 8e8fd88c..73b95d15 100644 --- a/src/x11/cursor.rs +++ b/src/x11/cursor.rs @@ -62,6 +62,7 @@ pub(super) fn get_xcursor(display: *mut x11::xlib::Display, cursor: MouseCursor) MouseCursor::Hand => loadn(&[b"hand2\0", b"hand1\0"]), MouseCursor::HandGrabbing => loadn(&[b"closedhand\0", b"grabbing\0"]), + MouseCursor::Pointer => loadn(&[b"hand2\0"]), MouseCursor::Help => load(b"question_arrow\0"), MouseCursor::Hidden => create_empty_cursor(display), From 5744a2b95f65261b3b9f9a95cebf10f1d00e3ffb Mon Sep 17 00:00:00 2001 From: Aymeric Nunge Date: Wed, 14 Sep 2022 14:49:30 +0300 Subject: [PATCH 06/13] set_mouse_cursor via SetCursor API --- src/win/cursor.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/win/mod.rs | 1 + src/win/window.rs | 11 +++++++---- 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 src/win/cursor.rs diff --git a/src/win/cursor.rs b/src/win/cursor.rs new file mode 100644 index 00000000..aaee35eb --- /dev/null +++ b/src/win/cursor.rs @@ -0,0 +1,38 @@ +use winapi::{ + shared::ntdef::PCWSTR, + um::winuser::{ + IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, IDC_NO, IDC_SIZEALL, IDC_WAIT, + }, +}; + +use crate::MouseCursor; + +impl MouseCursor { + pub(crate) fn to_windows_cursor(self) -> PCWSTR { + match self { + MouseCursor::Default => IDC_ARROW, + MouseCursor::Hand | MouseCursor::Pointer => IDC_HAND, + MouseCursor::HandGrabbing + | MouseCursor::Move + | MouseCursor::ZoomIn + | MouseCursor::ZoomOut + | MouseCursor::AllScroll => IDC_SIZEALL, + MouseCursor::Help => IDC_HELP, + MouseCursor::Text | MouseCursor::VerticalText => IDC_IBEAM, + MouseCursor::Working | MouseCursor::PtrWorking => IDC_WAIT, + MouseCursor::NotAllowed | MouseCursor::PtrNotAllowed => IDC_NO, + MouseCursor::Crosshair => IDC_CROSS, + MouseCursor::EResize + | MouseCursor::WResize + | MouseCursor::EwResize + | MouseCursor::ColResize => IDC_SIZEALL, + MouseCursor::NResize + | MouseCursor::SResize + | MouseCursor::NsResize + | MouseCursor::RowResize => IDC_SIZEALL, + MouseCursor::NeResize | MouseCursor::SwResize | MouseCursor::NeswResize => IDC_SIZEALL, + MouseCursor::NwResize | MouseCursor::SeResize | MouseCursor::NwseResize => IDC_SIZEALL, + _ => IDC_ARROW, + } + } +} diff --git a/src/win/mod.rs b/src/win/mod.rs index f66c2bdb..a7b9d3a1 100644 --- a/src/win/mod.rs +++ b/src/win/mod.rs @@ -1,5 +1,6 @@ mod drop_target; mod keyboard; mod window; +mod cursor; pub use window::*; diff --git a/src/win/window.rs b/src/win/window.rs index 3b21be34..51f9bd1c 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -6,7 +6,7 @@ use winapi::um::ole2::{RegisterDragDrop, OleInitialize, RevokeDragDrop}; use winapi::um::oleidl::LPDROPTARGET; use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, - GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, + GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, SetCursor, PostMessageW, RegisterClassW, ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, @@ -31,7 +31,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, Win32Handle}; const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1; use crate::{ - Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, Size, WindowEvent, + Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, Size, MouseCursor, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, }; @@ -433,7 +433,7 @@ unsafe fn register_wnd_class() -> ATOM { cbClsExtra: 0, cbWndExtra: 0, hIcon: null_mut(), - hCursor: LoadCursorW(null_mut(), IDC_ARROW), + hCursor: null_mut(), // If the class cursor is not NULL, the system restores the class cursor each time the mouse is moved. hbrBackground: null_mut(), lpszMenuName: null_mut(), }; @@ -761,7 +761,10 @@ impl Window<'_> { } pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { - //@TODO: Implement + unsafe { + let cursor = LoadCursorW(null_mut(), cursor.to_windows_cursor()); + SetCursor(cursor); + } } pub fn close(&mut self) { From b0096e34b187bff2a393fcc92b39736568f5b8ae Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 00:55:44 +0200 Subject: [PATCH 07/13] Revert "set_mouse_cursor via SetCursor API" This reverts commit 5744a2b95f65261b3b9f9a95cebf10f1d00e3ffb. --- src/win/cursor.rs | 38 -------------------------------------- src/win/mod.rs | 1 - src/win/window.rs | 11 ++++------- 3 files changed, 4 insertions(+), 46 deletions(-) delete mode 100644 src/win/cursor.rs diff --git a/src/win/cursor.rs b/src/win/cursor.rs deleted file mode 100644 index aaee35eb..00000000 --- a/src/win/cursor.rs +++ /dev/null @@ -1,38 +0,0 @@ -use winapi::{ - shared::ntdef::PCWSTR, - um::winuser::{ - IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, IDC_NO, IDC_SIZEALL, IDC_WAIT, - }, -}; - -use crate::MouseCursor; - -impl MouseCursor { - pub(crate) fn to_windows_cursor(self) -> PCWSTR { - match self { - MouseCursor::Default => IDC_ARROW, - MouseCursor::Hand | MouseCursor::Pointer => IDC_HAND, - MouseCursor::HandGrabbing - | MouseCursor::Move - | MouseCursor::ZoomIn - | MouseCursor::ZoomOut - | MouseCursor::AllScroll => IDC_SIZEALL, - MouseCursor::Help => IDC_HELP, - MouseCursor::Text | MouseCursor::VerticalText => IDC_IBEAM, - MouseCursor::Working | MouseCursor::PtrWorking => IDC_WAIT, - MouseCursor::NotAllowed | MouseCursor::PtrNotAllowed => IDC_NO, - MouseCursor::Crosshair => IDC_CROSS, - MouseCursor::EResize - | MouseCursor::WResize - | MouseCursor::EwResize - | MouseCursor::ColResize => IDC_SIZEALL, - MouseCursor::NResize - | MouseCursor::SResize - | MouseCursor::NsResize - | MouseCursor::RowResize => IDC_SIZEALL, - MouseCursor::NeResize | MouseCursor::SwResize | MouseCursor::NeswResize => IDC_SIZEALL, - MouseCursor::NwResize | MouseCursor::SeResize | MouseCursor::NwseResize => IDC_SIZEALL, - _ => IDC_ARROW, - } - } -} diff --git a/src/win/mod.rs b/src/win/mod.rs index a7b9d3a1..f66c2bdb 100644 --- a/src/win/mod.rs +++ b/src/win/mod.rs @@ -1,6 +1,5 @@ mod drop_target; mod keyboard; mod window; -mod cursor; pub use window::*; diff --git a/src/win/window.rs b/src/win/window.rs index 51f9bd1c..3b21be34 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -6,7 +6,7 @@ use winapi::um::ole2::{RegisterDragDrop, OleInitialize, RevokeDragDrop}; use winapi::um::oleidl::LPDROPTARGET; use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, - GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, SetCursor, PostMessageW, RegisterClassW, + GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, @@ -31,7 +31,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, Win32Handle}; const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1; use crate::{ - Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, Size, MouseCursor, WindowEvent, + Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, Size, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, }; @@ -433,7 +433,7 @@ unsafe fn register_wnd_class() -> ATOM { cbClsExtra: 0, cbWndExtra: 0, hIcon: null_mut(), - hCursor: null_mut(), // If the class cursor is not NULL, the system restores the class cursor each time the mouse is moved. + hCursor: LoadCursorW(null_mut(), IDC_ARROW), hbrBackground: null_mut(), lpszMenuName: null_mut(), }; @@ -761,10 +761,7 @@ impl Window<'_> { } pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { - unsafe { - let cursor = LoadCursorW(null_mut(), cursor.to_windows_cursor()); - SetCursor(cursor); - } + //@TODO: Implement } pub fn close(&mut self) { From 76886618c14dd0f5e9145d462ac26b372cbaa20e Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 00:55:44 +0200 Subject: [PATCH 08/13] Revert "added case for MouseCursor::Pointer" This reverts commit 21345380a7c0f91a3bf1aa72e7ee3d7ed909635b. --- src/x11/cursor.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/x11/cursor.rs b/src/x11/cursor.rs index 73b95d15..8e8fd88c 100644 --- a/src/x11/cursor.rs +++ b/src/x11/cursor.rs @@ -62,7 +62,6 @@ pub(super) fn get_xcursor(display: *mut x11::xlib::Display, cursor: MouseCursor) MouseCursor::Hand => loadn(&[b"hand2\0", b"hand1\0"]), MouseCursor::HandGrabbing => loadn(&[b"closedhand\0", b"grabbing\0"]), - MouseCursor::Pointer => loadn(&[b"hand2\0"]), MouseCursor::Help => load(b"question_arrow\0"), MouseCursor::Hidden => create_empty_cursor(display), From f57ba5168f0ad790bdfa4cefc58c08605cb90fe9 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 00:55:44 +0200 Subject: [PATCH 09/13] Revert "set_mouse_cursor self set to mut to follow the x11 impl" This reverts commit 8c6bf04187faa52b7bf3bd59454892c2b462dad7. --- src/win/window.rs | 2 +- src/window.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index 3b21be34..fe41efd6 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -760,7 +760,7 @@ impl Window<'_> { } } - pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { + pub fn set_mouse_cursor(&self, cursor: MouseCursor) { //@TODO: Implement } diff --git a/src/window.rs b/src/window.rs index 1b6b704d..8bbbb9da 100644 --- a/src/window.rs +++ b/src/window.rs @@ -117,7 +117,7 @@ impl<'a> Window<'a> { } /// Set the cursor to the given cursor type - pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { + pub fn set_mouse_cursor(&self, cursor: MouseCursor) { self.window.set_mouse_cursor(cursor); } From 3f68d36e0de6e902b3b8d4e60abc00114f8dd060 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 00:55:44 +0200 Subject: [PATCH 10/13] Revert "added Windows set_mouse_cursor stub" This reverts commit 4fb764ba2519ec7d2886e47ab09da4d9051f1558. --- src/win/window.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index fe41efd6..2c68b99c 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -760,10 +760,6 @@ impl Window<'_> { } } - pub fn set_mouse_cursor(&self, cursor: MouseCursor) { - //@TODO: Implement - } - pub fn close(&mut self) { unsafe { PostMessageW(self.state.hwnd, BV_WINDOW_MUST_CLOSE, 0, 0); From 8b3103863141bd282e15893f0c2735dd754f8151 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 01:14:58 +0200 Subject: [PATCH 11/13] Update macOS impl to objc2 --- Cargo.toml | 1 + src/macos/cursor.rs | 108 ++++++++++++++++++++++++-------------------- src/macos/window.rs | 13 +----- src/mouse_cursor.rs | 1 - src/window.rs | 5 -- 5 files changed, 62 insertions(+), 66 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 534fb563..96afbee0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,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 index 17846cce..557a23ed 100644 --- a/src/macos/cursor.rs +++ b/src/macos/cursor.rs @@ -1,53 +1,66 @@ -use cocoa::base::id; -use objc::{runtime::Sel, msg_send, sel, sel_impl, class}; +use objc2::__framework_prelude::Retained; +use objc2::runtime::{MessageReceiver, Sel}; +use objc2::{sel, ClassType}; +use objc2_app_kit::NSCursor; use crate::MouseCursor; #[derive(Debug)] pub enum Cursor { - Native(&'static str), - Undocumented(&'static str), + Native(fn() -> Retained), + Undocumented(Sel), } impl From for Cursor { fn from(cursor: MouseCursor) -> Self { match cursor { - MouseCursor::Default => Cursor::Native("arrowCursor"), - MouseCursor::Pointer => Cursor::Native("pointingHandCursor"), - MouseCursor::Hand => Cursor::Native("openHandCursor"), - MouseCursor::HandGrabbing => Cursor::Native("closedHandCursor"), - MouseCursor::Text => Cursor::Native("IBeamCursor"), - MouseCursor::VerticalText => Cursor::Native("IBeamCursorForVerticalLayout"), - MouseCursor::Copy => Cursor::Native("dragCopyCursor"), - MouseCursor::Alias => Cursor::Native("dragLinkCursor"), + 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("operationNotAllowedCursor") + 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:: => Cursor::Native("contextualMenuCursor"), - MouseCursor::Crosshair => Cursor::Native("crosshairCursor"), - MouseCursor::EResize => Cursor::Native("resizeRightCursor"), - MouseCursor::NResize => Cursor::Native("resizeUpCursor"), - MouseCursor::WResize => Cursor::Native("resizeLeftCursor"), - MouseCursor::SResize => Cursor::Native("resizeDownCursor"), - MouseCursor::EwResize | MouseCursor::ColResize => Cursor::Native("resizeLeftRightCursor"), - MouseCursor::NsResize | MouseCursor::RowResize => Cursor::Native("resizeUpDownCursor"), - MouseCursor::Help => Cursor::Undocumented("_helpCursor"), - MouseCursor::ZoomIn => Cursor::Undocumented("_zoomInCursor"), - MouseCursor::ZoomOut => Cursor::Undocumented("_zoomOutCursor"), - MouseCursor::NeResize => Cursor::Undocumented("_windowResizeNorthEastCursor"), - MouseCursor::NwResize => Cursor::Undocumented("_windowResizeNorthWestCursor"), - MouseCursor::SeResize => Cursor::Undocumented("_windowResizeSouthEastCursor"), - MouseCursor::SwResize => Cursor::Undocumented("_windowResizeSouthWestCursor"), - MouseCursor::NeswResize => Cursor::Undocumented("_windowResizeNorthEastSouthWestCursor"), - MouseCursor::NwseResize => Cursor::Undocumented("_windowResizeNorthWestSouthEastCursor"), + 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("busyButClickableCursor") + Cursor::Undocumented(sel!(busyButClickableCursor)) } - _ => Cursor::Native("arrowCursor"), - + _ => Cursor::Native(NSCursor::arrowCursor), // MouseCursor::Hidden => todo!(), // MouseCursor::Move => todo!(), // MouseCursor::AllScroll => todo!(), @@ -57,22 +70,21 @@ impl From for Cursor { } impl Cursor { - pub unsafe fn load(&self) -> id { + pub fn load(&self) -> Retained { match self { - Cursor::Native(cursor_name) => { - let sel = Sel::register(cursor_name); - msg_send![class!(NSCursor), performSelector: sel] - } - Cursor::Undocumented(cursor_name) => { - let class = class!(NSCursor); - let sel = Sel::register(cursor_name); - let sel = if msg_send![class, respondsToSelector: sel] { - sel - } else { - sel!(arrowCursor) - }; - msg_send![class, performSelector: sel] + Cursor::Native(loader) => loader(), + Cursor::Undocumented(sel) => { + let class = NSCursor::class(); + + if !class.responds_to(*sel) { + 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) } } } -} \ No newline at end of file +} diff --git a/src/macos/window.rs b/src/macos/window.rs index 065fe258..f56a0f74 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -154,20 +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); - unsafe { - let bounds: NSRect = msg_send![self.ns_view as id, bounds]; - let cursor = native_cursor.load(); - let _: () = msg_send![self.ns_view as id, - addCursorRect:bounds - cursor:cursor - ]; - } + self.view.addCursorRect_cursor(self.view.bounds(), &native_cursor.load()); } #[cfg(feature = "opengl")] diff --git a/src/mouse_cursor.rs b/src/mouse_cursor.rs index 885d1209..754e0297 100644 --- a/src/mouse_cursor.rs +++ b/src/mouse_cursor.rs @@ -4,7 +4,6 @@ pub enum MouseCursor { Default, Hand, HandGrabbing, - Pointer, Help, Hidden, diff --git a/src/window.rs b/src/window.rs index 2d5dcde6..da633c33 100644 --- a/src/window.rs +++ b/src/window.rs @@ -7,7 +7,6 @@ use raw_window_handle::{ use crate::event::{Event, EventStatus}; use crate::window_open_options::WindowOpenOptions; use crate::{MouseCursor, Size}; -use crate::MouseCursor; #[cfg(target_os = "macos")] use crate::macos as platform; @@ -100,10 +99,6 @@ impl<'a> Window<'a> { } /// Set the cursor to the given cursor type - pub fn set_mouse_cursor(&self, cursor: MouseCursor) { - self.window.set_mouse_cursor(cursor); - } - pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { self.window.set_mouse_cursor(cursor); } From 6796d9a9790e5e7cb29f3bbd4b5e64ed79442094 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 01:21:51 +0200 Subject: [PATCH 12/13] Fix fmt --- src/macos/mod.rs | 2 +- src/window.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/macos/mod.rs b/src/macos/mod.rs index ef4ee2bc..8b5a303b 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,6 +1,6 @@ +mod cursor; mod keyboard; mod view; mod window; -mod cursor; pub use window::*; diff --git a/src/window.rs b/src/window.rs index da633c33..25b53d1e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -98,7 +98,6 @@ impl<'a> Window<'a> { self.window.resize(size); } - /// Set the cursor to the given cursor type pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { self.window.set_mouse_cursor(cursor); } From 00213a5eaf36e1a553c7adbf3a1adeed0a1eae3c Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Sun, 14 Jun 2026 01:37:44 +0200 Subject: [PATCH 13/13] Fix undocumented cursor loading --- src/macos/cursor.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/macos/cursor.rs b/src/macos/cursor.rs index 557a23ed..27550134 100644 --- a/src/macos/cursor.rs +++ b/src/macos/cursor.rs @@ -1,6 +1,6 @@ use objc2::__framework_prelude::Retained; use objc2::runtime::{MessageReceiver, Sel}; -use objc2::{sel, ClassType}; +use objc2::{msg_send, sel, ClassType}; use objc2_app_kit::NSCursor; use crate::MouseCursor; @@ -76,7 +76,10 @@ impl Cursor { Cursor::Undocumented(sel) => { let class = NSCursor::class(); - if !class.responds_to(*sel) { + // 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(); }