Skip to content
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

Global NSEvent listener and some mouse methods #94

Merged
merged 4 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ default-target = "x86_64-apple-darwin"
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
bitmask-enum = "2.2.1"
block = "0.1.6"
core-foundation = "0.9"
core-graphics = "0.23"
Expand Down Expand Up @@ -104,4 +105,4 @@ name = "safe_area"
required-features = ["appkit"]
[[example]]
name = "popover"
required-features = ["appkit"]
required-features = ["appkit"]
109 changes: 102 additions & 7 deletions src/appkit/event/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
use bitmask_enum::bitmask;
use block::ConcreteBlock;

use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;

use crate::foundation::{id, nil, NSString};
use crate::events::EventType;
use crate::foundation::{id, nil, NSInteger, NSPoint, NSString};

/// An EventMask describes the type of event.
#[derive(Debug)]
#[bitmask(u64)]
pub enum EventMask {
KeyDown
LeftMouseDown = 1 << 1,
LeftMouseUp = 1 << 2,
RightMouseDown = 1 << 3,
RightMouseUp = 1 << 4,
MouseMoved = 1 << 5,
LeftMouseDragged = 1 << 6,
RightMouseDragged = 1 << 7,
MouseEntered = 1 << 8,
MouseExited = 1 << 9,
KeyDown = 1 << 10,
KeyUp = 1 << 11,
FlagsChanged = 1 << 12,
AppKitDefined = 1 << 13,
SystemDefined = 1 << 14,
ApplicationDefined = 1 << 15,
Periodic = 1 << 16,
CursorUpdate = 1 << 17,

ScrollWheel = 1 << 22,
TabletPoint = 1 << 23,
TabletProximity = 1 << 24,
OtherMouseDown = 1 << 25,
OtherMouseUp = 1 << 26,
OtherMouseDragged = 1 << 27,

Gesture = 1 << 29,
Magnify = 1 << 30,
Swipe = 1 << 31,
Rotate = 1 << 18,
BeginGesture = 1 << 19,
EndGesture = 1 << 20,

SmartMagnify = 1 << 32,
QuickLook = 1 << 33,
Pressure = 1 << 34,
DirectTouch = 1 << 37,

ChangeMode = 1 << 38
}

/// A wrapper over an `NSEvent`.
Expand All @@ -25,6 +64,16 @@ impl Event {
Event(unsafe { Id::from_ptr(objc) })
}

/// The event's type.
///
/// Corresponds to the `type` getter.
pub fn kind(&self) -> EventType {
let kind: NSUInteger = unsafe { msg_send![&*self.0, type] };

unsafe { ::std::mem::transmute(kind) }
}

/// The characters associated with a key-up or key-down event.
pub fn characters(&self) -> String {
// @TODO: Check here if key event, invalid otherwise.
// @TODO: Figure out if we can just return &str here, since the Objective-C side
Expand All @@ -34,6 +83,26 @@ impl Event {
characters.to_string()
}

/// The indices of the currently pressed mouse buttons.
pub fn pressed_mouse_buttons() -> NSUInteger {
unsafe { msg_send![class!(NSEvent), pressedMouseButtons] }
}

/// Reports the current mouse position in screen coordinates.
pub fn mouse_location() -> NSPoint {
unsafe { msg_send![class!(NSEvent), mouseLocation] }
}

/// The button number for a mouse event.
pub fn button_number(&self) -> NSInteger {
unsafe { msg_send![&*self.0, buttonNumber] }
}

/// The number of mouse clicks associated with a mouse-down or mouse-up event.
pub fn click_count(&self) -> NSInteger {
unsafe { msg_send![&*self.0, clickCount] }
}

/*pub fn contains_modifier_flags(&self, flags: &[EventModifierFlag]) -> bool {
let modifier_flags: NSUInteger = unsafe {
msg_send![&*self.0, modifierFlags]
Expand All @@ -47,13 +116,39 @@ impl Event {
false
}*/

/// Register an event handler with the system event stream. This method
/// Register an event handler with the local system event stream. This method
/// watches for events that occur _within the application_. Events outside
/// of the application require installing a `monitor_global_events` handler.
/// of the application require installing a `global_monitor` handler.
///
/// Note that in order to monitor all possible events, both local and global
/// monitors are required - the streams don't mix.
pub fn local_monitor<F>(mask: EventMask, handler: F) -> EventMonitor
where
F: Fn(Event) -> Option<Event> + Send + Sync + 'static
{
let block = ConcreteBlock::new(move |event: id| {
let evt = Event::new(event);

match handler(evt) {
Some(mut evt) => &mut *evt.0,
None => nil
}
});
let block = block.copy();

EventMonitor(unsafe {
msg_send![class!(NSEvent), addLocalMonitorForEventsMatchingMask:mask.bits
handler:block]
})
}

/// Register an event handler with the global system event stream. This method
/// watches for events that occur _outside the application_. Events within
/// the application require installing a `local_monitor` handler.
///
/// Note that in order to monitor all possible events, both local and global
/// monitors are required - the streams don't mix.
pub fn local_monitor<F>(_mask: EventMask, handler: F) -> EventMonitor
pub fn global_monitor<F>(mask: EventMask, handler: F) -> EventMonitor
where
F: Fn(Event) -> Option<Event> + Send + Sync + 'static
{
Expand All @@ -68,7 +163,7 @@ impl Event {
let block = block.copy();

EventMonitor(unsafe {
msg_send![class!(NSEvent), addLocalMonitorForEventsMatchingMask:1024
msg_send![class!(NSEvent), addGlobalMonitorForEventsMatchingMask:mask.bits
handler:block]
})
}
Expand Down
42 changes: 40 additions & 2 deletions src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,45 @@ impl From<&EventModifierFlag> for NSUInteger {

/// Represents an event type that you can request to be notified about.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(target_pointer_width = "32", repr(u32))]
#[cfg_attr(target_pointer_width = "64", repr(u64))]
pub enum EventType {
/// A keydown event.
KeyDown
LeftMouseDown = 1,
LeftMouseUp = 2,
RightMouseDown = 3,
RightMouseUp = 4,
MouseMoved = 5,
LeftMouseDragged = 6,
RightMouseDragged = 7,
MouseEntered = 8,
MouseExited = 9,
KeyDown = 10,
KeyUp = 11,
FlagsChanged = 12,
AppKitDefined = 13,
SystemDefined = 14,
ApplicationDefined = 15,
Periodic = 16,
CursorUpdate = 17,

ScrollWheel = 22,
TabletPoint = 23,
TabletProximity = 24,
OtherMouseDown = 25,
OtherMouseUp = 26,
OtherMouseDragged = 27,

Gesture = 29,
Magnify = 30,
Swipe = 31,
Rotate = 18,
BeginGesture = 19,
EndGesture = 20,

SmartMagnify = 32,
QuickLook = 33,
Pressure = 34,
DirectTouch = 37,

ChangeMode = 38
}
2 changes: 2 additions & 0 deletions src/foundation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ pub type NSInteger = libc::c_long;
/// Platform-specific.
#[cfg(target_pointer_width = "64")]
pub type NSUInteger = libc::c_ulong;

pub type NSPoint = core_graphics::geometry::CGPoint;
Loading