From 6585fd52250d0c59d90310f14f2f9ea511c2a79e Mon Sep 17 00:00:00 2001 From: Martin Mauch Date: Fri, 1 Nov 2024 02:30:05 +0100 Subject: [PATCH] fix(macOS): implement mouse drag (#1315) Add drag-and-drop capabilities for Mac OS. The code was taken from [RustDesk](https://github.com/rustdesk/rustdesk/blob/4f7e10bac6d09f9364edcd2983ce36b0a2e90cb9/libs/enigo/src/macos/macos_impl.rs#L191-L210). --- Cargo.lock | 35 +++++++++++++++++++++++++++-------- Cargo.toml | 3 ++- src/oskbd/macos.rs | 33 ++++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b5387c47..1831ecba6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,9 +233,9 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "core-foundation" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" dependencies = [ "core-foundation-sys", "libc", @@ -249,11 +249,11 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-graphics-types", "foreign-types", @@ -262,11 +262,11 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "libc", ] @@ -602,6 +602,7 @@ dependencies = [ "muldiv 1.0.1", "native-windows-gui", "nix 0.26.4", + "objc", "once_cell", "open", "parking_lot", @@ -751,6 +752,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.4" @@ -924,6 +934,15 @@ dependencies = [ "libc", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "object" version = "0.36.5" diff --git a/Cargo.toml b/Cargo.toml index cf664e4eb..3f3d956e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,8 @@ kanata-tcp-protocol = { path = "tcp_protocol" } [target.'cfg(target_os = "macos")'.dependencies] karabiner-driverkit = "0.1.3" -core-graphics = "0.23.2" +objc = "0.2.7" +core-graphics = "0.24.0" open = { version = "5", optional = true } [target.'cfg(target_os = "linux")'.dependencies] diff --git a/src/oskbd/macos.rs b/src/oskbd/macos.rs index b2e70d713..c04c8df42 100644 --- a/src/oskbd/macos.rs +++ b/src/oskbd/macos.rs @@ -16,6 +16,8 @@ use core_graphics::event_source::{CGEventSource, CGEventSourceStateID}; use kanata_parser::custom_action::*; use kanata_parser::keys::*; use karabiner_driverkit::*; +use objc::runtime::Class; +use objc::{msg_send, sel, sel_impl}; use std::convert::TryFrom; use std::fmt; use std::io; @@ -235,7 +237,6 @@ impl KbdOut { event.post(CGEventTapLocation::AnnotatedSession); Ok(()) } - pub fn scroll(&mut self, _direction: MWheelDirection, _distance: u16) -> Result<(), io::Error> { let event = Self::make_event()?; event.set_type(CGEventType::ScrollWheel); @@ -319,16 +320,38 @@ impl KbdOut { } pub fn move_mouse(&mut self, _mv: CalculatedMouseMove) -> Result<(), io::Error> { + let pressed = Self::pressed_buttons(); + + let event_type = if pressed & 1 > 0 { + CGEventType::LeftMouseDragged + } else if pressed & 2 > 0 { + CGEventType::RightMouseDragged + } else { + CGEventType::MouseMoved + }; + let event = Self::make_event()?; let mut mouse_position = event.location(); - let display = CGDisplay::main(); Self::apply_calculated_move(&_mv, &mut mouse_position); - display - .move_cursor_to_point(mouse_position) - .map_err(|_| io::Error::new(ErrorKind::Other, "failed to move mouse"))?; + if let Ok(event) = CGEvent::new_mouse_event( + Self::make_event_source()?, + event_type, + mouse_position, + CGMouseButton::Left, + ) { + event.post(CGEventTapLocation::HID); + } Ok(()) } + fn pressed_buttons() -> usize { + if let Some(ns_event) = Class::get("NSEvent") { + unsafe { msg_send![ns_event, pressedMouseButtons] } + } else { + 0 + } + } + pub fn move_mouse_many(&mut self, _moves: &[CalculatedMouseMove]) -> Result<(), io::Error> { let event = Self::make_event()?; let mut mouse_position = event.location();