Fix macOS modifier state for key combos

This commit is contained in:
PekingSpades 2026-04-07 15:42:29 +08:00
parent e0f2ad88c0
commit 7d33bee757
2 changed files with 122 additions and 22 deletions

95
key.go
View file

@ -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 {

View file

@ -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
#endif