diff --git a/key.go b/key.go index 7e99b6f..170ef39 100644 --- a/key.go +++ b/key.go @@ -372,19 +372,21 @@ func checkKeyCodes(k string) (key C.MMKeyCode, err error) { func checkKeyFlags(f string) (flags C.MMKeyFlags) { m := map[string]C.MMKeyFlags{ - "alt": C.MOD_ALT, - "ralt": C.MOD_ALT, - "lalt": C.MOD_ALT, - "cmd": C.MOD_META, - "rcmd": C.MOD_META, - "lcmd": C.MOD_META, - "ctrl": C.MOD_CONTROL, - "rctrl": C.MOD_CONTROL, - "lctrl": C.MOD_CONTROL, - "shift": C.MOD_SHIFT, - "rshift": C.MOD_SHIFT, - "lshift": C.MOD_SHIFT, - "none": C.MOD_NONE, + "alt": C.MOD_ALT, + "ralt": C.MOD_ALT, + "lalt": C.MOD_ALT, + "cmd": C.MOD_META, + "command": C.MOD_META, + "rcmd": C.MOD_META, + "lcmd": C.MOD_META, + "ctrl": C.MOD_CONTROL, + "control": C.MOD_CONTROL, + "rctrl": C.MOD_CONTROL, + "lctrl": C.MOD_CONTROL, + "shift": C.MOD_SHIFT, + "rshift": C.MOD_SHIFT, + "lshift": C.MOD_SHIFT, + "none": C.MOD_NONE, } if v, ok := m[f]; ok { @@ -408,6 +410,51 @@ func getFlagsFromValue(value []string) (flags C.MMKeyFlags) { return } +func modifierFlagForKeyName(key string) (C.MMKeyFlags, bool) { + flag := checkKeyFlags(key) + return flag, flag != C.MOD_NONE +} + +func modifierKeyEventDownDarwin(keyArr []string, pid int) C.MMKeyFlags { + var active C.MMKeyFlags + + for _, key := range keyArr { + flag, ok := modifierFlagForKeyName(key) + if !ok { + continue + } + + keyCode, err := checkKeyCodes(key) + if err != nil { + continue + } + + active |= flag + C.toggleKeyCode(keyCode, true, active, C.uintptr(pid)) + MilliSleep(1) + } + + return active +} + +func modifierKeyEventUpDarwin(keyArr []string, pid int, active C.MMKeyFlags) { + for i := len(keyArr) - 1; i >= 0; i-- { + flag, ok := modifierFlagForKeyName(keyArr[i]) + if !ok { + continue + } + + keyCode, err := checkKeyCodes(keyArr[i]) + if err != nil { + continue + } + + active &^= flag + C.toggleKeyCode(keyCode, false, active, C.uintptr(pid)) + MilliSleep(1) + } +} + func upKeyArr(keyArr []string, pid int) { for i := 0; i < len(keyArr); i++ { key1, _ := checkKeyCodes(keyArr[i]) @@ -422,6 +469,14 @@ func keyTaps(k string, keyArr []string, pid int) error { return err } + if runtime.GOOS == "darwin" && len(keyArr) > 0 { + active := modifierKeyEventDownDarwin(keyArr, pid) + tapKeyCode(key, active, C.uintptr(pid)) + MilliSleep(KeySleep) + modifierKeyEventUpDarwin(keyArr, pid, active) + return nil + } + tapKeyCode(key, flags, C.uintptr(pid)) MilliSleep(KeySleep) upKeyArr(keyArr, pid) @@ -451,6 +506,20 @@ func keyTogglesB(k string, down bool, keyArr []string, pid int) error { return err } + if runtime.GOOS == "darwin" && len(keyArr) > 0 { + if down { + active := modifierKeyEventDownDarwin(keyArr, pid) + C.toggleKeyCode(key, C.bool(down), active, C.uintptr(pid)) + MilliSleep(KeySleep) + return nil + } + + C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid)) + MilliSleep(KeySleep) + modifierKeyEventUpDarwin(keyArr, pid, flags) + return nil + } + C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid)) MilliSleep(KeySleep) if !down { diff --git a/key/keypress_c.h b/key/keypress_c.h index b93eeaf..49f7473 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -66,6 +66,29 @@ return 0; } + static CGEventSourceRef CreateKeyboardEventSource(void) { + return CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); + } + + static CGEventFlags modifierFlagForKeyCode(MMKeyCode code) { + if (code == K_META || code == K_LMETA || code == K_RMETA) { + return kCGEventFlagMaskCommand; + } + if (code == K_ALT || code == K_LALT || code == K_RALT) { + return kCGEventFlagMaskAlternate; + } + if (code == K_CONTROL || code == K_LCONTROL || code == K_RCONTROL) { + return kCGEventFlagMaskControl; + } + if (code == K_SHIFT || code == K_LSHIFT || code == K_RSHIFT) { + return kCGEventFlagMaskShift; + } + if (code == K_CAPSLOCK) { + return kCGEventFlagMaskAlphaShift; + } + return 0; + } + static io_connect_t _getAuxiliaryKeyDriver(void) { static mach_port_t sEventDrvrRef = 0; mach_port_t masterPort, service, iter; @@ -176,19 +199,27 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; event.compound.misc.L[0] = evtInfo; - kr = IOHIDPostEvent(_getAuxiliaryKeyDriver(), + kr = IOHIDPostEvent(_getAuxiliaryKeyDriver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE); assert(KERN_SUCCESS == kr); } else { - CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventFlags modifierFlag = modifierFlagForKeyCode(code); + CGEventFlags eventFlags = (CGEventFlags)flags; + CGEventType eventType = down ? kCGEventKeyDown : kCGEventKeyUp; + if (modifierFlag != 0) { + eventType = kCGEventFlagsChanged; + if (eventFlags == 0 && down) { + eventFlags = modifierFlag; + } + } + + CGEventSourceRef source = CreateKeyboardEventSource(); CGEventRef keyEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)code, down); assert(keyEvent != NULL); - CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp); - if (flags != 0) { - CGEventSetFlags(keyEvent, (CGEventFlags) flags); - } - + CGEventSetType(keyEvent, eventType); + CGEventSetFlags(keyEvent, eventFlags); + SendTo(pid, keyEvent); CFRelease(source); } @@ -276,7 +307,7 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { convert characters to a keycode, but does not support adding modifier flags. It is only used in typeString(). -- if you need modifier keys, use the above functions instead. */ - CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventSourceRef source = CreateKeyboardEventSource(); CGEventRef keyEvent = CGEventCreateKeyboardEvent(source, 0, down); if (keyEvent == NULL) { fputs("Could not create keyboard event.\n", stderr); @@ -357,4 +388,4 @@ void unicodeType(const unsigned value, uintptr pid, int8_t isPid) { int input_utf(const char *utf){ return 0; } -#endif \ No newline at end of file +#endif