Global NSEvent listener and some mouse methods (#94)
* Support for all NSEvent types and configurable event monitoring * Useful mouse event methods * rustfmt nightly fixes * Use standard kind naming convention
This commit is contained in:
parent
aedcfe1c65
commit
01507f7642
|
@ -19,6 +19,7 @@ default-target = "x86_64-apple-darwin"
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitmask-enum = "2.2.1"
|
||||||
block = "0.1.6"
|
block = "0.1.6"
|
||||||
core-foundation = "0.9"
|
core-foundation = "0.9"
|
||||||
core-graphics = "0.23"
|
core-graphics = "0.23"
|
||||||
|
@ -104,4 +105,4 @@ name = "safe_area"
|
||||||
required-features = ["appkit"]
|
required-features = ["appkit"]
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "popover"
|
name = "popover"
|
||||||
required-features = ["appkit"]
|
required-features = ["appkit"]
|
||||||
|
|
|
@ -1,15 +1,54 @@
|
||||||
|
use bitmask_enum::bitmask;
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel, sel_impl};
|
||||||
use objc_id::Id;
|
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.
|
/// An EventMask describes the type of event.
|
||||||
#[derive(Debug)]
|
#[bitmask(u64)]
|
||||||
pub enum EventMask {
|
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`.
|
/// A wrapper over an `NSEvent`.
|
||||||
|
@ -25,6 +64,16 @@ impl Event {
|
||||||
Event(unsafe { Id::from_ptr(objc) })
|
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 {
|
pub fn characters(&self) -> String {
|
||||||
// @TODO: Check here if key event, invalid otherwise.
|
// @TODO: Check here if key event, invalid otherwise.
|
||||||
// @TODO: Figure out if we can just return &str here, since the Objective-C side
|
// @TODO: Figure out if we can just return &str here, since the Objective-C side
|
||||||
|
@ -34,6 +83,26 @@ impl Event {
|
||||||
characters.to_string()
|
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 {
|
/*pub fn contains_modifier_flags(&self, flags: &[EventModifierFlag]) -> bool {
|
||||||
let modifier_flags: NSUInteger = unsafe {
|
let modifier_flags: NSUInteger = unsafe {
|
||||||
msg_send![&*self.0, modifierFlags]
|
msg_send![&*self.0, modifierFlags]
|
||||||
|
@ -47,13 +116,13 @@ impl Event {
|
||||||
false
|
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
|
/// 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
|
/// Note that in order to monitor all possible events, both local and global
|
||||||
/// monitors are required - the streams don't mix.
|
/// monitors are required - the streams don't mix.
|
||||||
pub fn local_monitor<F>(_mask: EventMask, handler: F) -> EventMonitor
|
pub fn local_monitor<F>(mask: EventMask, handler: F) -> EventMonitor
|
||||||
where
|
where
|
||||||
F: Fn(Event) -> Option<Event> + Send + Sync + 'static
|
F: Fn(Event) -> Option<Event> + Send + Sync + 'static
|
||||||
{
|
{
|
||||||
|
@ -68,7 +137,33 @@ impl Event {
|
||||||
let block = block.copy();
|
let block = block.copy();
|
||||||
|
|
||||||
EventMonitor(unsafe {
|
EventMonitor(unsafe {
|
||||||
msg_send![class!(NSEvent), addLocalMonitorForEventsMatchingMask:1024
|
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 global_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), addGlobalMonitorForEventsMatchingMask:mask.bits
|
||||||
handler:block]
|
handler:block]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,45 @@ impl From<&EventModifierFlag> for NSUInteger {
|
||||||
|
|
||||||
/// Represents an event type that you can request to be notified about.
|
/// Represents an event type that you can request to be notified about.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
#[cfg_attr(target_pointer_width = "32", repr(u32))]
|
||||||
|
#[cfg_attr(target_pointer_width = "64", repr(u64))]
|
||||||
pub enum EventType {
|
pub enum EventType {
|
||||||
/// A keydown event.
|
LeftMouseDown = 1,
|
||||||
KeyDown
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,3 +86,5 @@ pub type NSInteger = libc::c_long;
|
||||||
/// Platform-specific.
|
/// Platform-specific.
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
pub type NSUInteger = libc::c_ulong;
|
pub type NSUInteger = libc::c_ulong;
|
||||||
|
|
||||||
|
pub type NSPoint = core_graphics::geometry::CGPoint;
|
||||||
|
|
Loading…
Reference in a new issue