core_graphics_helmer_fork/event.rs
1#![allow(non_upper_case_globals)]
2use crate::event_source::CGEventSource;
3use crate::geometry::CGPoint;
4use core_foundation::{
5 base::{CFRelease, CFRetain, CFTypeID, TCFType},
6 mach_port::{CFMachPort, CFMachPortRef},
7};
8use foreign_types::ForeignType;
9use libc::c_void;
10use std::mem::ManuallyDrop;
11
12pub type CGEventField = u32;
13pub type CGKeyCode = u16;
14pub type CGScrollEventUnit = u32;
15
16bitflags! {
17 /// Flags for events
18 ///
19 /// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
20 #[repr(C)]
21 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
22 pub struct CGEventFlags: u64 {
23 const CGEventFlagNull = 0;
24
25 // Device-independent modifier key bits.
26 const CGEventFlagAlphaShift = 0x00010000;
27 const CGEventFlagShift = 0x00020000;
28 const CGEventFlagControl = 0x00040000;
29 const CGEventFlagAlternate = 0x00080000;
30 const CGEventFlagCommand = 0x00100000;
31
32 // Special key identifiers.
33 const CGEventFlagHelp = 0x00400000;
34 const CGEventFlagSecondaryFn = 0x00800000;
35
36 // Identifies key events from numeric keypad area on extended keyboards.
37 const CGEventFlagNumericPad = 0x00200000;
38
39 // Indicates if mouse/pen movement events are not being coalesced
40 const CGEventFlagNonCoalesced = 0x00000100;
41 }
42}
43
44/// Key codes for keys that are independent of keyboard layout.
45///
46/// [Ref](https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.13.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h)
47#[repr(C)]
48pub struct KeyCode;
49impl KeyCode {
50 pub const RETURN: CGKeyCode = 0x24;
51 pub const TAB: CGKeyCode = 0x30;
52 pub const SPACE: CGKeyCode = 0x31;
53 pub const DELETE: CGKeyCode = 0x33;
54 pub const ESCAPE: CGKeyCode = 0x35;
55 pub const COMMAND: CGKeyCode = 0x37;
56 pub const SHIFT: CGKeyCode = 0x38;
57 pub const CAPS_LOCK: CGKeyCode = 0x39;
58 pub const OPTION: CGKeyCode = 0x3A;
59 pub const CONTROL: CGKeyCode = 0x3B;
60 pub const RIGHT_COMMAND: CGKeyCode = 0x36;
61 pub const RIGHT_SHIFT: CGKeyCode = 0x3C;
62 pub const RIGHT_OPTION: CGKeyCode = 0x3D;
63 pub const RIGHT_CONTROL: CGKeyCode = 0x3E;
64 pub const FUNCTION: CGKeyCode = 0x3F;
65 pub const VOLUME_UP: CGKeyCode = 0x48;
66 pub const VOLUME_DOWN: CGKeyCode = 0x49;
67 pub const MUTE: CGKeyCode = 0x4A;
68 pub const F1: CGKeyCode = 0x7A;
69 pub const F2: CGKeyCode = 0x78;
70 pub const F3: CGKeyCode = 0x63;
71 pub const F4: CGKeyCode = 0x76;
72 pub const F5: CGKeyCode = 0x60;
73 pub const F6: CGKeyCode = 0x61;
74 pub const F7: CGKeyCode = 0x62;
75 pub const F8: CGKeyCode = 0x64;
76 pub const F9: CGKeyCode = 0x65;
77 pub const F10: CGKeyCode = 0x6D;
78 pub const F11: CGKeyCode = 0x67;
79 pub const F12: CGKeyCode = 0x6F;
80 pub const F13: CGKeyCode = 0x69;
81 pub const F14: CGKeyCode = 0x6B;
82 pub const F15: CGKeyCode = 0x71;
83 pub const F16: CGKeyCode = 0x6A;
84 pub const F17: CGKeyCode = 0x40;
85 pub const F18: CGKeyCode = 0x4F;
86 pub const F19: CGKeyCode = 0x50;
87 pub const F20: CGKeyCode = 0x5A;
88 pub const HELP: CGKeyCode = 0x72;
89 pub const HOME: CGKeyCode = 0x73;
90 pub const PAGE_UP: CGKeyCode = 0x74;
91 pub const FORWARD_DELETE: CGKeyCode = 0x75;
92 pub const END: CGKeyCode = 0x77;
93 pub const PAGE_DOWN: CGKeyCode = 0x79;
94 pub const LEFT_ARROW: CGKeyCode = 0x7B;
95 pub const RIGHT_ARROW: CGKeyCode = 0x7C;
96 pub const DOWN_ARROW: CGKeyCode = 0x7D;
97 pub const UP_ARROW: CGKeyCode = 0x7E;
98}
99
100#[repr(C)]
101pub struct ScrollEventUnit {}
102impl ScrollEventUnit {
103 pub const PIXEL: CGScrollEventUnit = 0;
104 pub const LINE: CGScrollEventUnit = 1;
105}
106
107/// Constants that specify the different types of input events.
108///
109/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
110#[repr(u32)]
111#[derive(Clone, Copy, Debug)]
112pub enum CGEventType {
113 Null = 0,
114
115 // Mouse events.
116 LeftMouseDown = 1,
117 LeftMouseUp = 2,
118 RightMouseDown = 3,
119 RightMouseUp = 4,
120 MouseMoved = 5,
121 LeftMouseDragged = 6,
122 RightMouseDragged = 7,
123
124 // Keyboard events.
125 KeyDown = 10,
126 KeyUp = 11,
127 FlagsChanged = 12,
128
129 // Specialized control devices.
130 ScrollWheel = 22,
131 TabletPointer = 23,
132 TabletProximity = 24,
133 OtherMouseDown = 25,
134 OtherMouseUp = 26,
135 OtherMouseDragged = 27,
136
137 // Out of band event types. These are delivered to the event tap callback
138 // to notify it of unusual conditions that disable the event tap.
139 TapDisabledByTimeout = 0xFFFFFFFE,
140 TapDisabledByUserInput = 0xFFFFFFFF,
141}
142
143/// Constants used as keys to access specialized fields in low-level events.
144///
145/// [Ref](https://developer.apple.com/documentation/coregraphics/cgeventfield)
146pub struct EventField;
147impl EventField {
148 /// Key to access an integer field that contains the mouse button event
149 /// number. Matching mouse-down and mouse-up events will have the same
150 /// event number.
151 pub const MOUSE_EVENT_NUMBER: CGEventField = 0;
152
153 /// Key to access an integer field that contains the mouse button click
154 /// state. A click state of 1 represents a single click. A click state of
155 /// 2 represents a double-click. A click state of 3 represents a
156 /// triple-click.
157 pub const MOUSE_EVENT_CLICK_STATE: CGEventField = 1;
158
159 /// Key to access a double field that contains the mouse button pressure.
160 /// The pressure value may range from 0 to 1, with 0 representing the
161 /// mouse being up. This value is commonly set by tablet pens mimicking a
162 /// mouse.
163 pub const MOUSE_EVENT_PRESSURE: CGEventField = 2;
164
165 /// Key to access an integer field that contains the mouse button number.
166 pub const MOUSE_EVENT_BUTTON_NUMBER: CGEventField = 3;
167
168 /// Key to access an integer field that contains the horizontal mouse
169 /// delta since the last mouse movement event.
170 pub const MOUSE_EVENT_DELTA_X: CGEventField = 4;
171
172 /// Key to access an integer field that contains the vertical mouse delta
173 /// since the last mouse movement event.
174 pub const MOUSE_EVENT_DELTA_Y: CGEventField = 5;
175
176 /// Key to access an integer field. The value is non-zero if the event
177 /// should be ignored by the Inkwell subsystem.
178 pub const MOUSE_EVENT_INSTANT_MOUSER: CGEventField = 6;
179
180 /// Key to access an integer field that encodes the mouse event subtype as
181 /// a `kCFNumberIntType`.
182 pub const MOUSE_EVENT_SUB_TYPE: CGEventField = 7;
183
184 /// Key to access an integer field, non-zero when this is an autorepeat of
185 /// a key-down, and zero otherwise.
186 pub const KEYBOARD_EVENT_AUTOREPEAT: CGEventField = 8;
187
188 /// Key to access an integer field that contains the virtual keycode of the
189 /// key-down or key-up event.
190 pub const KEYBOARD_EVENT_KEYCODE: CGEventField = 9;
191
192 /// Key to access an integer field that contains the keyboard type
193 /// identifier.
194 pub const KEYBOARD_EVENT_KEYBOARD_TYPE: CGEventField = 10;
195
196 /// Key to access an integer field that contains scrolling data. This field
197 /// typically contains the change in vertical position since the last
198 /// scrolling event from a Mighty Mouse scroller or a single-wheel mouse
199 /// scroller.
200 pub const SCROLL_WHEEL_EVENT_DELTA_AXIS_1: CGEventField = 11;
201
202 /// Key to access an integer field that contains scrolling data. This field
203 /// typically contains the change in horizontal position since the last
204 /// scrolling event from a Mighty Mouse scroller.
205 pub const SCROLL_WHEEL_EVENT_DELTA_AXIS_2: CGEventField = 12;
206
207 /// Key to access a field that contains scrolling data. The scrolling data
208 /// represents a line-based or pixel-based change in vertical position
209 /// since the last scrolling event from a Mighty Mouse scroller or a
210 /// single-wheel mouse scroller. The scrolling data uses a fixed-point
211 /// 16.16 signed integer format. If this key is passed to
212 /// `CGEventGetDoubleValueField`, the fixed-point value is converted to a
213 /// double value.
214 pub const SCROLL_WHEEL_EVENT_FIXED_POINT_DELTA_AXIS_1: CGEventField = 93;
215
216 /// Key to access a field that contains scrolling data. The scrolling data
217 /// represents a line-based or pixel-based change in horizontal position
218 /// since the last scrolling event from a Mighty Mouse scroller. The
219 /// scrolling data uses a fixed-point 16.16 signed integer format. If this
220 /// key is passed to `CGEventGetDoubleValueField`, the fixed-point value is
221 /// converted to a double value.
222 pub const SCROLL_WHEEL_EVENT_FIXED_POINT_DELTA_AXIS_2: CGEventField = 94;
223
224 /// Key to access an integer field that contains pixel-based scrolling
225 /// data. The scrolling data represents the change in vertical position
226 /// since the last scrolling event from a Mighty Mouse scroller or a
227 /// single-wheel mouse scroller.
228 pub const SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1: CGEventField = 96;
229
230 /// Key to access an integer field that contains pixel-based scrolling
231 /// data. The scrolling data represents the change in horizontal position
232 /// since the last scrolling event from a Mighty Mouse scroller.
233 pub const SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2: CGEventField = 97;
234
235 /// Key to access an integer field that indicates whether the event should
236 /// be ignored by the Inkwell subsystem. If the value is non-zero, the
237 /// event should be ignored.
238 pub const SCROLL_WHEEL_EVENT_INSTANT_MOUSER: CGEventField = 14;
239
240 /// Key to access an integer field that contains the absolute X coordinate
241 /// in tablet space at full tablet resolution.
242 pub const TABLET_EVENT_POINT_X: CGEventField = 15;
243
244 /// Key to access an integer field that contains the absolute Y coordinate
245 /// in tablet space at full tablet resolution.
246 pub const TABLET_EVENT_POINT_Y: CGEventField = 16;
247
248 /// Key to access an integer field that contains the absolute Z coordinate
249 /// in tablet space at full tablet resolution.
250 pub const TABLET_EVENT_POINT_Z: CGEventField = 17;
251
252 /// Key to access an integer field that contains the tablet button state.
253 /// Bit 0 is the first button, and a set bit represents a closed or pressed
254 /// button. Up to 16 buttons are supported.
255 pub const TABLET_EVENT_POINT_BUTTONS: CGEventField = 18;
256
257 /// Key to access a double field that contains the tablet pen pressure. A
258 /// value of 0.0 represents no pressure, and 1.0 represents maximum
259 /// pressure.
260 pub const TABLET_EVENT_POINT_PRESSURE: CGEventField = 19;
261
262 /// Key to access a double field that contains the horizontal tablet pen
263 /// tilt. A value of 0 represents no tilt, and 1 represents maximum tilt.
264 pub const TABLET_EVENT_TILT_X: CGEventField = 20;
265
266 /// Key to access a double field that contains the vertical tablet pen
267 /// tilt. A value of 0 represents no tilt, and 1 represents maximum tilt.
268 pub const TABLET_EVENT_TILT_Y: CGEventField = 21;
269
270 /// Key to access a double field that contains the tablet pen rotation.
271 pub const TABLET_EVENT_ROTATION: CGEventField = 22;
272
273 /// Key to access a double field that contains the tangential pressure on
274 /// the device. A value of 0.0 represents no pressure, and 1.0 represents
275 /// maximum pressure.
276 pub const TABLET_EVENT_TANGENTIAL_PRESSURE: CGEventField = 23;
277
278 /// Key to access an integer field that contains the system-assigned unique
279 /// device ID.
280 pub const TABLET_EVENT_DEVICE_ID: CGEventField = 24;
281
282 /// Key to access an integer field that contains a vendor-specified value.
283 pub const TABLET_EVENT_VENDOR_1: CGEventField = 25;
284
285 /// Key to access an integer field that contains a vendor-specified value.
286 pub const TABLET_EVENT_VENDOR_2: CGEventField = 26;
287
288 /// Key to access an integer field that contains a vendor-specified value.
289 pub const TABLET_EVENT_VENDOR_3: CGEventField = 27;
290
291 /// Key to access an integer field that contains the vendor-defined ID,
292 /// typically the USB vendor ID.
293 pub const TABLET_PROXIMITY_EVENT_VENDOR_ID: CGEventField = 28;
294
295 /// Key to access an integer field that contains the vendor-defined tablet
296 /// ID, typically the USB product ID.
297 pub const TABLET_PROXIMITY_EVENT_TABLET_ID: CGEventField = 29;
298
299 /// Key to access an integer field that contains the vendor-defined ID of
300 /// the pointing device.
301 pub const TABLET_PROXIMITY_EVENT_POINTER_ID: CGEventField = 30;
302
303 /// Key to access an integer field that contains the system-assigned
304 /// device ID.
305 pub const TABLET_PROXIMITY_EVENT_DEVICE_ID: CGEventField = 31;
306
307 /// Key to access an integer field that contains the system-assigned
308 /// unique tablet ID.
309 pub const TABLET_PROXIMITY_EVENT_SYSTEM_TABLET_ID: CGEventField = 32;
310
311 /// Key to access an integer field that contains the vendor-assigned
312 /// pointer type.
313 pub const TABLET_PROXIMITY_EVENT_VENDOR_POINTER_TYPE: CGEventField = 33;
314
315 /// Key to access an integer field that contains the vendor-defined
316 /// pointer serial number.
317 pub const TABLET_PROXIMITY_EVENT_VENDOR_POINTER_SERIAL_NUMBER: CGEventField = 34;
318
319 /// Key to access an integer field that contains the vendor-defined unique
320 /// ID.
321 pub const TABLET_PROXIMITY_EVENT_VENDOR_UNIQUE_ID: CGEventField = 35;
322
323 /// Key to access an integer field that contains the device capabilities
324 /// mask.
325 pub const TABLET_PROXIMITY_EVENT_CAPABILITY_MASK: CGEventField = 36;
326
327 /// Key to access an integer field that contains the pointer type.
328 pub const TABLET_PROXIMITY_EVENT_POINTER_TYPE: CGEventField = 37;
329
330 /// Key to access an integer field that indicates whether the pen is in
331 /// proximity to the tablet. The value is non-zero if the pen is in
332 /// proximity to the tablet and zero when leaving the tablet.
333 pub const TABLET_PROXIMITY_EVENT_ENTER_PROXIMITY: CGEventField = 38;
334
335 /// Key to access a field that contains the event target process serial
336 /// number. The value is a 64-bit value.
337 pub const EVENT_TARGET_PROCESS_SERIAL_NUMBER: CGEventField = 39;
338
339 /// Key to access a field that contains the event target Unix process ID.
340 pub const EVENT_TARGET_UNIX_PROCESS_ID: CGEventField = 40;
341
342 /// Key to access a field that contains the event source Unix process ID.
343 pub const EVENT_SOURCE_UNIX_PROCESS_ID: CGEventField = 41;
344
345 /// Key to access a field that contains the event source user-supplied
346 /// data, up to 64 bits.
347 pub const EVENT_SOURCE_USER_DATA: CGEventField = 42;
348
349 /// Key to access a field that contains the event source Unix effective UID.
350 pub const EVENT_SOURCE_USER_ID: CGEventField = 43;
351
352 /// Key to access a field that contains the event source Unix effective
353 /// GID.
354 pub const EVENT_SOURCE_GROUP_ID: CGEventField = 44;
355
356 /// Key to access a field that contains the event source state ID used to
357 /// create this event.
358 pub const EVENT_SOURCE_STATE_ID: CGEventField = 45;
359
360 /// Key to access an integer field that indicates whether a scrolling event
361 /// contains continuous, pixel-based scrolling data. The value is non-zero
362 /// when the scrolling data is pixel-based and zero when the scrolling data
363 /// is line-based.
364 pub const SCROLL_WHEEL_EVENT_IS_CONTINUOUS: CGEventField = 88;
365
366 /// Added in 10.5; made public in 10.7.
367 pub const MOUSE_EVENT_WINDOW_UNDER_MOUSE_POINTER: CGEventField = 91;
368 pub const MOUSE_EVENT_WINDOW_UNDER_MOUSE_POINTER_THAT_CAN_HANDLE_THIS_EVENT: CGEventField = 92;
369}
370
371// Constants that specify buttons on a one, two, or three-button mouse.
372#[repr(C)]
373#[derive(Clone, Copy, Debug)]
374pub enum CGMouseButton {
375 Left,
376 Right,
377 Center,
378}
379
380/// Possible tapping points for events.
381#[repr(C)]
382#[derive(Clone, Copy, Debug)]
383pub enum CGEventTapLocation {
384 HID,
385 Session,
386 AnnotatedSession,
387}
388
389// The next three enums are taken from:
390// [Ref](https://github.com/phracker/MacOSX-SDKs/blob/ef9fe35d5691b6dd383c8c46d867a499817a01b6/MacOSX10.15.sdk/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGEventTypes.h)
391/* Constants that specify where a new event tap is inserted into the list of
392active event taps. */
393#[repr(u32)]
394#[derive(Clone, Copy, Debug)]
395pub enum CGEventTapPlacement {
396 HeadInsertEventTap = 0,
397 TailAppendEventTap,
398}
399
400/* Constants that specify whether a new event tap is an active filter or a
401passive listener. */
402#[repr(u32)]
403#[derive(Clone, Copy, Debug)]
404pub enum CGEventTapOptions {
405 Default = 0x00000000,
406 ListenOnly = 0x00000001,
407}
408
409pub type CGEventMask = u64;
410/* Generate an event mask for a single type of event. */
411macro_rules! CGEventMaskBit {
412 ($eventType:expr) => {
413 1 << $eventType as CGEventMask
414 };
415}
416
417pub type CGEventTapProxy = *const c_void;
418pub type CGEventTapCallBackFn<'tap_life> =
419 Box<dyn Fn(CGEventTapProxy, CGEventType, &CGEvent) -> Option<CGEvent> + 'tap_life>;
420type CGEventTapCallBackInternal = unsafe extern "C" fn(
421 proxy: CGEventTapProxy,
422 etype: CGEventType,
423 event: crate::sys::CGEventRef,
424 user_info: *const c_void,
425) -> crate::sys::CGEventRef;
426
427unsafe extern "C" fn cg_event_tap_callback_internal(
428 _proxy: CGEventTapProxy,
429 _etype: CGEventType,
430 _event: crate::sys::CGEventRef,
431 _user_info: *const c_void,
432) -> crate::sys::CGEventRef {
433 let callback = _user_info as *mut CGEventTapCallBackFn;
434 let event = CGEvent::from_ptr(_event);
435 let new_event = (*callback)(_proxy, _etype, &event);
436 let event = match new_event {
437 Some(new_event) => new_event,
438 None => event,
439 };
440 ManuallyDrop::new(event).as_ptr()
441}
442
443/// ```no_run
444///extern crate core_foundation;
445///use core_foundation::runloop::{kCFRunLoopCommonModes, CFRunLoop};
446///use core_graphics::event::{CGEventTap, CGEventTapLocation, CGEventTapPlacement, CGEventTapOptions, CGEventType};
447///let current = CFRunLoop::get_current();
448///match CGEventTap::new(
449/// CGEventTapLocation::HID,
450/// CGEventTapPlacement::HeadInsertEventTap,
451/// CGEventTapOptions::Default,
452/// vec![CGEventType::MouseMoved],
453/// |_a, _b, d| {
454/// println!("{:?}", d.location());
455/// None
456/// },
457/// ) {
458/// Ok(tap) => unsafe {
459/// let loop_source = tap
460/// .mach_port
461/// .create_runloop_source(0)
462/// .expect("Somethings is bad ");
463/// current.add_source(&loop_source, kCFRunLoopCommonModes);
464/// tap.enable();
465/// CFRunLoop::run_current();
466/// },
467/// Err(_) => (assert!(false)),
468/// }
469/// ```
470pub struct CGEventTap<'tap_life> {
471 pub mach_port: CFMachPort,
472 pub callback_ref:
473 Box<dyn Fn(CGEventTapProxy, CGEventType, &CGEvent) -> Option<CGEvent> + 'tap_life>,
474}
475
476impl<'tap_life> CGEventTap<'tap_life> {
477 pub fn new<F: Fn(CGEventTapProxy, CGEventType, &CGEvent) -> Option<CGEvent> + 'tap_life>(
478 tap: CGEventTapLocation,
479 place: CGEventTapPlacement,
480 options: CGEventTapOptions,
481 events_of_interest: std::vec::Vec<CGEventType>,
482 callback: F,
483 ) -> Result<CGEventTap<'tap_life>, ()> {
484 let event_mask: CGEventMask = events_of_interest
485 .iter()
486 .fold(CGEventType::Null as CGEventMask, |mask, &etype| {
487 mask | CGEventMaskBit!(etype)
488 });
489 let cb = Box::new(Box::new(callback) as CGEventTapCallBackFn);
490 let cbr = Box::into_raw(cb);
491 unsafe {
492 let event_tap_ref = CGEventTapCreate(
493 tap,
494 place,
495 options,
496 event_mask,
497 cg_event_tap_callback_internal,
498 cbr as *const c_void,
499 );
500
501 if !event_tap_ref.is_null() {
502 Ok(Self {
503 mach_port: (CFMachPort::wrap_under_create_rule(event_tap_ref)),
504 callback_ref: Box::from_raw(cbr),
505 })
506 } else {
507 let _ = Box::from_raw(cbr);
508 Err(())
509 }
510 }
511 }
512
513 pub fn enable(&self) {
514 unsafe { CGEventTapEnable(self.mach_port.as_concrete_TypeRef(), true) }
515 }
516}
517
518foreign_type! {
519 #[doc(hidden)]
520 pub unsafe type CGEvent {
521 type CType = crate::sys::CGEvent;
522 fn drop = |p| CFRelease(p as *mut _);
523 fn clone = |p| CFRetain(p as *const _) as *mut _;
524 }
525}
526
527impl CGEvent {
528 pub fn type_id() -> CFTypeID {
529 unsafe { CGEventGetTypeID() }
530 }
531
532 pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
533 unsafe {
534 let event_ref = CGEventCreate(source.as_ptr());
535 if !event_ref.is_null() {
536 Ok(Self::from_ptr(event_ref))
537 } else {
538 Err(())
539 }
540 }
541 }
542
543 pub fn new_keyboard_event(
544 source: CGEventSource,
545 keycode: CGKeyCode,
546 keydown: bool,
547 ) -> Result<CGEvent, ()> {
548 unsafe {
549 let event_ref = CGEventCreateKeyboardEvent(source.as_ptr(), keycode, keydown);
550 if !event_ref.is_null() {
551 Ok(Self::from_ptr(event_ref))
552 } else {
553 Err(())
554 }
555 }
556 }
557
558 pub fn new_mouse_event(
559 source: CGEventSource,
560 mouse_type: CGEventType,
561 mouse_cursor_position: CGPoint,
562 mouse_button: CGMouseButton,
563 ) -> Result<CGEvent, ()> {
564 unsafe {
565 let event_ref = CGEventCreateMouseEvent(
566 source.as_ptr(),
567 mouse_type,
568 mouse_cursor_position,
569 mouse_button,
570 );
571 if !event_ref.is_null() {
572 Ok(Self::from_ptr(event_ref))
573 } else {
574 Err(())
575 }
576 }
577 }
578
579 #[cfg(feature = "highsierra")]
580 pub fn new_scroll_event(
581 source: CGEventSource,
582 units: CGScrollEventUnit,
583 wheel_count: u32,
584 wheel1: i32,
585 wheel2: i32,
586 wheel3: i32,
587 ) -> Result<CGEvent, ()> {
588 unsafe {
589 let event_ref = CGEventCreateScrollWheelEvent2(
590 source.as_ptr(),
591 units,
592 wheel_count,
593 wheel1,
594 wheel2,
595 wheel3,
596 );
597 if !event_ref.is_null() {
598 Ok(Self::from_ptr(event_ref))
599 } else {
600 Err(())
601 }
602 }
603 }
604
605 pub fn post(&self, tap_location: CGEventTapLocation) {
606 unsafe {
607 CGEventPost(tap_location, self.as_ptr());
608 }
609 }
610
611 pub fn post_from_tap(&self, tap_proxy: CGEventTapProxy) {
612 unsafe {
613 CGEventTapPostEvent(tap_proxy, self.as_ptr());
614 }
615 }
616
617 pub fn location(&self) -> CGPoint {
618 unsafe { CGEventGetLocation(self.as_ptr()) }
619 }
620
621 #[cfg(feature = "elcapitan")]
622 pub fn post_to_pid(&self, pid: libc::pid_t) {
623 unsafe {
624 CGEventPostToPid(pid, self.as_ptr());
625 }
626 }
627
628 pub fn set_flags(&self, flags: CGEventFlags) {
629 unsafe {
630 CGEventSetFlags(self.as_ptr(), flags);
631 }
632 }
633
634 pub fn get_flags(&self) -> CGEventFlags {
635 unsafe { CGEventGetFlags(self.as_ptr()) }
636 }
637
638 pub fn set_type(&self, event_type: CGEventType) {
639 unsafe {
640 CGEventSetType(self.as_ptr(), event_type);
641 }
642 }
643
644 pub fn get_type(&self) -> CGEventType {
645 unsafe { CGEventGetType(self.as_ptr()) }
646 }
647
648 pub fn set_string_from_utf16_unchecked(&self, buf: &[u16]) {
649 let buflen = buf.len() as libc::c_ulong;
650 unsafe {
651 CGEventKeyboardSetUnicodeString(self.as_ptr(), buflen, buf.as_ptr());
652 }
653 }
654
655 pub fn set_string(&self, string: &str) {
656 let buf: Vec<u16> = string.encode_utf16().collect();
657 self.set_string_from_utf16_unchecked(&buf);
658 }
659
660 pub fn get_integer_value_field(&self, field: CGEventField) -> i64 {
661 unsafe { CGEventGetIntegerValueField(self.as_ptr(), field) }
662 }
663
664 pub fn set_integer_value_field(&self, field: CGEventField, value: i64) {
665 unsafe { CGEventSetIntegerValueField(self.as_ptr(), field, value) }
666 }
667
668 pub fn get_double_value_field(&self, field: CGEventField) -> f64 {
669 unsafe { CGEventGetDoubleValueField(self.as_ptr(), field) }
670 }
671
672 pub fn set_double_value_field(&self, field: CGEventField, value: f64) {
673 unsafe { CGEventSetDoubleValueField(self.as_ptr(), field, value) }
674 }
675}
676
677#[cfg_attr(feature = "link", link(name = "CoreGraphics", kind = "framework"))]
678extern "C" {
679 /// Return the type identifier for the opaque type `CGEventRef'.
680 fn CGEventGetTypeID() -> CFTypeID;
681
682 /// Return a new event using the event source `source'. If `source' is NULL,
683 /// the default source is used.
684 fn CGEventCreate(source: crate::sys::CGEventSourceRef) -> crate::sys::CGEventRef;
685
686 /// Return a new keyboard event.
687 ///
688 /// The event source may be taken from another event, or may be NULL. Based
689 /// on the virtual key code values entered, the appropriate key down, key up,
690 /// or flags changed events are generated.
691 ///
692 /// All keystrokes needed to generate a character must be entered, including
693 /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
694 /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
695 /// and 'z' key must be released:
696 fn CGEventCreateKeyboardEvent(
697 source: crate::sys::CGEventSourceRef,
698 keycode: CGKeyCode,
699 keydown: bool,
700 ) -> crate::sys::CGEventRef;
701
702 /// Return a new mouse event.
703 ///
704 /// The event source may be taken from another event, or may be NULL.
705 /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
706 /// should be the position of the mouse cursor in global coordinates.
707 /// `mouseButton' should be the button that's changing state; `mouseButton'
708 /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
709 /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
710 ///
711 /// The current implementation of the event system supports a maximum of
712 /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
713 /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
714 /// the center button, and the remaining buttons are in USB device order.
715 fn CGEventCreateMouseEvent(
716 source: crate::sys::CGEventSourceRef,
717 mouseType: CGEventType,
718 mouseCursorPosition: CGPoint,
719 mouseButton: CGMouseButton,
720 ) -> crate::sys::CGEventRef;
721
722 /// A non-variadic variant version of CGEventCreateScrollWheelEvent.
723 ///
724 /// Returns a new Quartz scrolling event.
725 ///
726 /// This function allows you to create a scrolling event and customize the
727 /// event before posting it to the event system.
728 #[cfg(feature = "highsierra")]
729 fn CGEventCreateScrollWheelEvent2(
730 source: crate::sys::CGEventSourceRef,
731 units: CGScrollEventUnit,
732 wheelCount: u32,
733 wheel1: i32,
734 wheel2: i32,
735 wheel3: i32,
736 ) -> crate::sys::CGEventRef;
737
738 /// Post an event into the event stream at a specified location.
739 ///
740 /// This function posts the specified event immediately before any event taps
741 /// instantiated for that location, and the event passes through any such
742 /// taps.
743 fn CGEventPost(tapLocation: CGEventTapLocation, event: crate::sys::CGEventRef);
744
745 fn CGEventTapPostEvent(tapProxy: CGEventTapProxy, event: crate::sys::CGEventRef);
746
747 #[cfg(feature = "elcapitan")]
748 /// Post an event to a specified process ID
749 fn CGEventPostToPid(pid: libc::pid_t, event: crate::sys::CGEventRef);
750
751 /// Set the event flags of an event.
752 fn CGEventSetFlags(event: crate::sys::CGEventRef, flags: CGEventFlags);
753
754 /// Return the event flags of an event.
755 fn CGEventGetFlags(event: crate::sys::CGEventRef) -> CGEventFlags;
756
757 /// Return the location of an event in global display coordinates.
758 /// CGPointZero is returned if event is not a valid crate::sys::CGEventRef.
759 fn CGEventGetLocation(event: crate::sys::CGEventRef) -> CGPoint;
760
761 /// Set the event type of an event.
762 fn CGEventSetType(event: crate::sys::CGEventRef, eventType: CGEventType);
763
764 /// Return the event type of an event (left mouse down, for example).
765 fn CGEventGetType(event: crate::sys::CGEventRef) -> CGEventType;
766
767 /// Set the Unicode string associated with a keyboard event.
768 ///
769 /// By default, the system translates the virtual key code in a keyboard
770 /// event into a Unicode string based on the keyboard ID in the event
771 /// source. This function allows you to manually override this string.
772 /// Note that application frameworks may ignore the Unicode string in a
773 /// keyboard event and do their own translation based on the virtual
774 /// keycode and perceived event state.
775 fn CGEventKeyboardSetUnicodeString(
776 event: crate::sys::CGEventRef,
777 length: libc::c_ulong,
778 string: *const u16,
779 );
780
781 /// Return the integer value of a field in an event.
782 fn CGEventGetIntegerValueField(event: crate::sys::CGEventRef, field: CGEventField) -> i64;
783
784 /// Set the integer value of a field in an event.
785 ///
786 /// Before calling this function, the event type must be set using a typed
787 /// event creation function such as `CGEventCreateMouseEvent', or by
788 /// calling `CGEventSetType'.
789 ///
790 /// If you are creating a mouse event generated by a tablet, call this
791 /// function and specify the field `kCGMouseEventSubtype' with a value of
792 /// `kCGEventMouseSubtypeTabletPoint' or
793 /// `kCGEventMouseSubtypeTabletProximity' before setting other parameters.
794 fn CGEventSetIntegerValueField(event: crate::sys::CGEventRef, field: CGEventField, value: i64);
795
796 /// Return the floating-point value of a field in an event.
797 ///
798 /// In cases where the field value is represented within the event by a fixed
799 /// point number or an integer, the result is scaled to the appropriate range
800 /// as part of creating the floating-point representation.
801 fn CGEventGetDoubleValueField(event: crate::sys::CGEventRef, field: CGEventField) -> f64;
802
803 /// Set the floating-point value of a field in an event.
804 ///
805 /// Before calling this function, the event type must be set using a typed
806 /// event creation function such as `CGEventCreateMouseEvent', or by calling
807 /// `CGEventSetType'.
808 ///
809 /// In cases where the field’s value is represented within the event by a
810 /// fixed point number or integer, the value parameter is scaled as needed
811 /// and converted to the appropriate type.
812 fn CGEventSetDoubleValueField(event: crate::sys::CGEventRef, field: CGEventField, value: f64);
813
814 // ::sys::CGEventTapRef is actually an CFMachPortRef
815 fn CGEventTapCreate(
816 tap: CGEventTapLocation,
817 place: CGEventTapPlacement,
818 options: CGEventTapOptions,
819 eventsOfInterest: CGEventMask,
820 callback: CGEventTapCallBackInternal,
821 userInfo: *const c_void,
822 ) -> CFMachPortRef;
823
824 fn CGEventTapEnable(tap: CFMachPortRef, enable: bool);
825
826}