-
Notifications
You must be signed in to change notification settings - Fork 84
Add screen absolute mouse position for resizing window. #211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| use crate::MouseCursor; | ||
| use cocoa::base::id; | ||
| use objc::{class, msg_send, sel, sel_impl}; | ||
|
|
||
| pub fn mouse_cursor_to_nscursor(cursor: MouseCursor) -> id { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please move these mouse cursor changes into a separate PR. |
||
| unsafe { | ||
| let nscursor_class = class!(NSCursor); | ||
| match cursor { | ||
| MouseCursor::Default => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::Hand => msg_send![nscursor_class, pointingHandCursor], | ||
| MouseCursor::HandGrabbing => msg_send![nscursor_class, closedHandCursor], | ||
| MouseCursor::Help => msg_send![nscursor_class, arrowCursor], // No help cursor | ||
| MouseCursor::Hidden => { | ||
| // Return a null cursor for hidden - will be handled specially | ||
| std::ptr::null_mut() | ||
| } | ||
| MouseCursor::Text => msg_send![nscursor_class, IBeamCursor], | ||
| MouseCursor::VerticalText => msg_send![nscursor_class, IBeamCursor], | ||
| MouseCursor::Working => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::PtrWorking => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::NotAllowed => msg_send![nscursor_class, operationNotAllowedCursor], | ||
| MouseCursor::PtrNotAllowed => msg_send![nscursor_class, operationNotAllowedCursor], | ||
| MouseCursor::ZoomIn => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::ZoomOut => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::Alias => msg_send![nscursor_class, dragLinkCursor], | ||
| MouseCursor::Copy => msg_send![nscursor_class, dragCopyCursor], | ||
| MouseCursor::Move => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::AllScroll => msg_send![nscursor_class, arrowCursor], | ||
| MouseCursor::Cell => msg_send![nscursor_class, crosshairCursor], | ||
| MouseCursor::Crosshair => msg_send![nscursor_class, crosshairCursor], | ||
| MouseCursor::EResize => msg_send![nscursor_class, resizeRightCursor], | ||
| MouseCursor::NResize => msg_send![nscursor_class, resizeUpCursor], | ||
| MouseCursor::NeResize => msg_send![nscursor_class, arrowCursor], // No built-in | ||
| MouseCursor::NwResize => msg_send![nscursor_class, arrowCursor], // No built-in | ||
| MouseCursor::SResize => msg_send![nscursor_class, resizeDownCursor], | ||
| MouseCursor::SeResize => msg_send![nscursor_class, arrowCursor], // No built-in | ||
| MouseCursor::SwResize => msg_send![nscursor_class, arrowCursor], // No built-in | ||
| MouseCursor::WResize => msg_send![nscursor_class, resizeLeftCursor], | ||
| MouseCursor::EwResize => msg_send![nscursor_class, resizeLeftRightCursor], | ||
| MouseCursor::NsResize => msg_send![nscursor_class, resizeUpDownCursor], | ||
| MouseCursor::NwseResize => { | ||
| // Use private API for diagonal resize cursor | ||
| msg_send![nscursor_class, _windowResizeNorthWestSouthEastCursor] | ||
| } | ||
| MouseCursor::NeswResize => { | ||
| // Use private API for diagonal resize cursor | ||
| msg_send![nscursor_class, _windowResizeNorthEastSouthWestCursor] | ||
| } | ||
| MouseCursor::ColResize => msg_send![nscursor_class, resizeLeftRightCursor], | ||
| MouseCursor::RowResize => msg_send![nscursor_class, resizeUpDownCursor], | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -393,17 +393,38 @@ extern "C" fn update_tracking_areas(this: &Object, _self: Sel, _: id) { | |
| extern "C" fn mouse_moved(this: &Object, _sel: Sel, event: id) { | ||
| let state = unsafe { WindowState::from_view(this) }; | ||
|
|
||
| let point: NSPoint = unsafe { | ||
| // Window-relative position (existing behavior) | ||
| let window_point: NSPoint = unsafe { | ||
| let point = NSEvent::locationInWindow(event); | ||
|
|
||
| msg_send![this, convertPoint:point fromView:nil] | ||
| }; | ||
|
|
||
| // Screen-absolute position (new!) | ||
| // NSEvent::mouseLocation returns screen coordinates with Y=0 at BOTTOM | ||
| // We need to flip Y-axis to match Windows/X11 convention (Y=0 at TOP) | ||
| let screen_point: NSPoint = unsafe { | ||
| NSEvent::mouseLocation(event) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the correct method to use. The
The fact that the |
||
| }; | ||
|
|
||
| // Get the screen height to flip Y coordinate | ||
| let screen_height = unsafe { | ||
| let screen: id = msg_send![class!(NSScreen), mainScreen]; | ||
| let frame: NSRect = msg_send![screen, frame]; | ||
| frame.size.height | ||
| }; | ||
|
|
||
| let modifiers = unsafe { NSEvent::modifierFlags(event) }; | ||
|
|
||
| let position = Point { x: point.x, y: point.y }; | ||
| let position = Point { x: window_point.x, y: window_point.y }; | ||
| // Flip Y-axis: convert from bottom-origin to top-origin | ||
| let screen_position = Point { | ||
| x: screen_point.x, | ||
| y: screen_height - screen_point.y | ||
| }; | ||
|
|
||
| state.trigger_event(Event::Mouse(MouseEvent::CursorMoved { | ||
| position, | ||
| screen_position, | ||
| modifiers: make_modifiers(modifiers), | ||
| })); | ||
| } | ||
|
|
@@ -430,9 +451,29 @@ extern "C" fn scroll_wheel(this: &Object, _: Sel, event: id) { | |
| })); | ||
| } | ||
|
|
||
| fn get_drag_position(sender: id) -> Point { | ||
| let point: NSPoint = unsafe { msg_send![sender, draggingLocation] }; | ||
| Point::new(point.x, point.y) | ||
| fn get_drag_position(sender: id) -> (Point, Point) { | ||
| // Window-relative position | ||
| let window_point: NSPoint = unsafe { msg_send![sender, draggingLocation] }; | ||
|
|
||
| // For drag events, we need to get screen position from the global mouse location | ||
| // since NSDraggingInfo doesn't provide it directly | ||
| // NSEvent::mouseLocation returns coordinates with Y=0 at BOTTOM | ||
| let screen_point: NSPoint = unsafe { | ||
| let ns_event_class: id = msg_send![class!(NSEvent), class]; | ||
| msg_send![ns_event_class, mouseLocation] | ||
| }; | ||
|
|
||
| // Get screen height to flip Y coordinate (convert from bottom-origin to top-origin) | ||
| let screen_height = unsafe { | ||
| let screen: id = msg_send![class!(NSScreen), mainScreen]; | ||
| let frame: NSRect = msg_send![screen, frame]; | ||
| frame.size.height | ||
| }; | ||
|
|
||
| ( | ||
| Point::new(window_point.x, window_point.y), | ||
| Point::new(screen_point.x, screen_height - screen_point.y) | ||
| ) | ||
| } | ||
|
|
||
| fn get_drop_data(sender: id) -> DropData { | ||
|
|
@@ -473,9 +514,11 @@ extern "C" fn dragging_entered(this: &Object, _sel: Sel, sender: id) -> NSUInteg | |
| let state = unsafe { WindowState::from_view(this) }; | ||
| let modifiers = state.keyboard_state().last_mods(); | ||
| let drop_data = get_drop_data(sender); | ||
| let (position, screen_position) = get_drag_position(sender); | ||
|
|
||
| let event = MouseEvent::DragEntered { | ||
| position: get_drag_position(sender), | ||
| position, | ||
| screen_position, | ||
| modifiers: make_modifiers(modifiers), | ||
| data: drop_data, | ||
| }; | ||
|
|
@@ -487,9 +530,11 @@ extern "C" fn dragging_updated(this: &Object, _sel: Sel, sender: id) -> NSUInteg | |
| let state = unsafe { WindowState::from_view(this) }; | ||
| let modifiers = state.keyboard_state().last_mods(); | ||
| let drop_data = get_drop_data(sender); | ||
| let (position, screen_position) = get_drag_position(sender); | ||
|
|
||
| let event = MouseEvent::DragMoved { | ||
| position: get_drag_position(sender), | ||
| position, | ||
| screen_position, | ||
| modifiers: make_modifiers(modifiers), | ||
| data: drop_data, | ||
| }; | ||
|
|
@@ -508,9 +553,11 @@ extern "C" fn perform_drag_operation(this: &Object, _sel: Sel, sender: id) -> BO | |
| let state = unsafe { WindowState::from_view(this) }; | ||
| let modifiers = state.keyboard_state().last_mods(); | ||
| let drop_data = get_drop_data(sender); | ||
| let (position, screen_position) = get_drag_position(sender); | ||
|
|
||
| let event = MouseEvent::DragDropped { | ||
| position: get_drag_position(sender), | ||
| position, | ||
| screen_position, | ||
| modifiers: make_modifiers(modifiers), | ||
| data: drop_data, | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than adding monitor-relative coordinates to every event with a cursor position, I think it would be better to provide an explicit way to use the
Windowstruct to convert between window-relative and monitor-relative coordinates (probably by just providing a method to get the current window location).