aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2018-10-11 17:07:04 +0200
committerTeddy Wing2018-10-11 17:07:04 +0200
commitf21fce30bf46105ab805b596de60568f108a59d3 (patch)
treebd74bf58e3f16e34c01bd7ca7329915476adc242
parent18d499d07928a7276d45acaf7b061d4fb2a7e953 (diff)
downloaddome-key-map-f21fce30bf46105ab805b596de60568f108a59d3.tar.bz2
Add a function to send media key events
Media keys (rewind, play/pause, fast forward on Mac function keys) are different from normal keys. These use a different API, and sending events to simulate those keys is different. Here's a first stab at getting something working for posting simulated media key events. This will be used for new special keys in mapping actions. Haven't tested this at all yet, just happy that it finally compiles. Follow the two Stack Overflow answers referenced in the comments (from Albert https://stackoverflow.com/users/133374/albert and Nick Sweeting https://stackoverflow.com/users/2156113/nick-sweeting). Add the `core-graphics` crate to give us access to `CGEvent`, `CGKeyCode`, and related types. Also include some commented `CGKeyCode` definitions for future use.
-rw-r--r--Cargo.toml1
-rw-r--r--src/key_code.rs153
-rw-r--r--src/lib.rs4
3 files changed, 157 insertions, 1 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0d918d2..905af39 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ version = "0.0.1"
autopilot = "0.1.7"
cocoa = "0.18.0"
combine = "3.4.0"
+core-graphics = "0.17.2"
getopts = "0.2.18"
libc = "0.2.43"
log = "0.4.5"
diff --git a/src/key_code.rs b/src/key_code.rs
new file mode 100644
index 0000000..e148555
--- /dev/null
+++ b/src/key_code.rs
@@ -0,0 +1,153 @@
+use cocoa::appkit::{
+ NSEvent,
+ NSEventModifierFlags,
+ NSEventSubtype::NSScreenChangedEventType,
+ NSEventType::NSSystemDefined,
+};
+use cocoa::base::nil;
+use cocoa::foundation::NSPoint;
+use core_graphics::event::{CGEvent, CGEventTapLocation, CGKeyCode, KeyCode};
+
+// impl KeyCode {
+// pub const RETURN: CGKeyCode = 0x24;
+// pub const TAB: CGKeyCode = 0x30;
+// pub const SPACE: CGKeyCode = 0x31;
+// pub const DELETE: CGKeyCode = 0x33;
+// pub const ESCAPE: CGKeyCode = 0x35;
+// pub const COMMAND: CGKeyCode = 0x37;
+// pub const SHIFT: CGKeyCode = 0x38;
+// pub const CAPS_LOCK: CGKeyCode = 0x39;
+// pub const OPTION: CGKeyCode = 0x3A;
+// pub const CONTROL: CGKeyCode = 0x3B;
+// pub const RIGHT_COMMAND: CGKeyCode = 0x36;
+// pub const RIGHT_SHIFT: CGKeyCode = 0x3C;
+// pub const RIGHT_OPTION: CGKeyCode = 0x3D;
+// pub const RIGHT_CONTROL: CGKeyCode = 0x3E;
+// pub const FUNCTION: CGKeyCode = 0x3F;
+// pub const VOLUME_UP: CGKeyCode = 0x48;
+// pub const VOLUME_DOWN: CGKeyCode = 0x49;
+// pub const MUTE: CGKeyCode = 0x4A;
+// }
+
+// kVK_F13 = 0x69,
+// kVK_F14 = 0x6B,
+// kVK_F15 = 0x71,
+// kVK_F16 = 0x6A,
+// kVK_F17 = 0x40,
+// kVK_F18 = 0x4F,
+// kVK_F19 = 0x50,
+// kVK_F20 = 0x5A,
+//
+// enum {
+// kVK_Return = 0x24,
+// kVK_Tab = 0x30,
+// kVK_Space = 0x31,
+// kVK_Delete = 0x33,
+// kVK_Escape = 0x35,
+// kVK_Command = 0x37,
+// kVK_Shift = 0x38,
+// kVK_CapsLock = 0x39,
+// kVK_Option = 0x3A,
+// kVK_Control = 0x3B,
+// kVK_RightCommand = 0x36,
+// kVK_RightShift = 0x3C,
+// kVK_RightOption = 0x3D,
+// kVK_RightControl = 0x3E,
+// kVK_Function = 0x3F,
+// kVK_F17 = 0x40,
+// kVK_VolumeUp = 0x48,
+// kVK_VolumeDown = 0x49,
+// kVK_Mute = 0x4A,
+// kVK_F18 = 0x4F,
+// kVK_F19 = 0x50,
+// kVK_F20 = 0x5A,
+// kVK_F5 = 0x60,
+// kVK_F6 = 0x61,
+// kVK_F7 = 0x62,
+// kVK_F3 = 0x63,
+// kVK_F8 = 0x64,
+// kVK_F9 = 0x65,
+// kVK_F11 = 0x67,
+// kVK_F13 = 0x69,
+// kVK_F16 = 0x6A,
+// kVK_F14 = 0x6B,
+// kVK_F10 = 0x6D,
+// kVK_F12 = 0x6F,
+// kVK_F15 = 0x71,
+// kVK_Help = 0x72,
+// kVK_Home = 0x73,
+// kVK_PageUp = 0x74,
+// kVK_ForwardDelete = 0x75,
+// kVK_F4 = 0x76,
+// kVK_End = 0x77,
+// kVK_F2 = 0x78,
+// kVK_PageDown = 0x79,
+// kVK_F1 = 0x7A,
+// kVK_LeftArrow = 0x7B,
+// kVK_RightArrow = 0x7C,
+// kVK_DownArrow = 0x7D,
+// kVK_UpArrow = 0x7E
+// };
+
+
+
+ // unsafe fn otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
+ // _: Self,
+ // eventType: NSEventType,
+ // location: NSPoint,
+ // modifierFlags: NSEventModifierFlags,
+ // timestamp: NSTimeInterval,
+ // windowNumber: NSInteger,
+ // context: id /* (NSGraphicsContext *) */,
+ // subtype: NSEventSubtype,
+ // data1: NSInteger,
+ // data2: NSInteger) -> id /* (NSEvent *) */
+
+
+// https://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac/11048135#11048135
+// https://stackoverflow.com/questions/10459085/cocoa-simulate-macbook-upper-keys-multimedia-keys/50574159#50574159
+unsafe fn press_play() {
+ let NX_KEYTYPE_PLAY = 16;
+ let code = NX_KEYTYPE_PLAY;
+
+ let key_down = NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
+ nil,
+ NSSystemDefined,
+ NSPoint::new(0.0, 0.0),
+ NSEventModifierFlags::NSDeviceIndependentModifierFlagsMask,
+ 0.0,
+ 0,
+ nil,
+ NSScreenChangedEventType,
+ (code << 16 as i32) | (0xa << 8 as i32),
+ -1
+ );
+ let event = key_down.CGEvent() as *mut CGEvent;
+ let event = &*event;
+ event.post(CGEventTapLocation::HID);
+
+ let key_up = NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
+ nil,
+ NSSystemDefined,
+ NSPoint::new(0.0, 0.0),
+ NSEventModifierFlags::NSDeviceIndependentModifierFlagsMask,
+ 0.0,
+ 0,
+ nil,
+ NSScreenChangedEventType,
+ (code << 16 as i32) | (0xb << 8 as i32),
+ -1
+ );
+ let event = key_down.CGEvent() as *mut CGEvent;
+ let event = &*event;
+ event.post(CGEventTapLocation::HID);
+}
+
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn send_media_key_event() {
+ press_play();
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 1f57edb..5ce31eb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,10 +1,11 @@
#![recursion_limit="128"]
extern crate autopilot;
-// extern crate cocoa;
+extern crate cocoa;
#[macro_use]
extern crate combine;
+extern crate core_graphics;
extern crate getopts;
extern crate libc;
@@ -15,6 +16,7 @@ extern crate xdg;
mod cocoa_bridge;
mod config;
+mod key_code;
mod parser;
use parser::{Action, HeadphoneButton, MapAction, MapGroup, MapKind};