当我尝试在 MacOS 上以编程方式模拟按键时。 我发现有些按键会导致“Fn”粘滞。
以下代码结果为“Fn”+“h”。 谁能帮忙解释一下这是否是故意的?
#include <stdio.h>
#include <Carbon/Carbon.h>
void simulate_key(CGEventSourceRef source, CGKeyCode key, bool key_down)
{
CGEventRef event = CGEventCreateKeyboardEvent(source, key, key_down);
CGEventPost(kCGSessionEventTap, event);
CFRelease(event);
sleep(1);
}
void print33(void) {
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
printf("simulate #: ");
fflush(stdout);
simulate_key(source, kVK_Shift, true);
simulate_key(source, kVK_ANSI_3, true);
simulate_key(source, kVK_ANSI_3, false);
simulate_key(source, kVK_Shift, false);
// sticky Fn, after clicking Home.
simulate_key(source, kVK_Home, true);
simulate_key(source, kVK_Home, false);
printf("\nSimulate h after Home.\n");
fflush(stdout);
// Simulate h. The behavior seems Fn + h.
simulate_key(source, kVK_ANSI_H, true);
simulate_key(source, kVK_ANSI_H, false);
// So as simulating e and d...
CFRelease(source);
}
int main(int argc, const char * argv[]) {
print33();
return 0;
}
我也尝试过打印
CGEventFlags
。显示kCGEventFlagMaskSecondaryFn
已设置。但不知道是不是有副作用。当我只是模拟 Fn
键时,如何防止设置 Home
标志。
#include <stdio.h>
#include <Carbon/Carbon.h>
void simulate_key(CGEventSourceRef source, CGKeyCode key, bool key_down)
{
CGEventRef event = CGEventCreateKeyboardEvent(source, key, key_down);
// CGEventSetFlags(event, 0);
CGEventFlags flags = CGEventGetFlags(event);
printf("event flags: %llX\n", (int64_t)flags);
CGEventPost(kCGSessionEventTap, event);
CFRelease(event);
sleep(1);
}
void print33(void) {
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
// printf("simulate #: ");
// fflush(stdout);
// simulate_key(source, kVK_Shift, true);
// simulate_key(source, kVK_ANSI_3, true);
// simulate_key(source, kVK_ANSI_3, false);
// simulate_key(source, kVK_Shift, false);
printf("kCGEventFlagMaskAlphaShift: %llX\n", (int64_t)kCGEventFlagMaskAlphaShift);
printf("kCGEventFlagMaskShift: %llX\n", (int64_t)kCGEventFlagMaskShift);
printf("kCGEventFlagMaskControl: %llX\n", (int64_t)kCGEventFlagMaskControl);
printf("kCGEventFlagMaskAlternate: %llX\n", (int64_t)kCGEventFlagMaskAlternate);
printf("kCGEventFlagMaskCommand: %llX\n", (int64_t)kCGEventFlagMaskCommand);
printf("kCGEventFlagMaskHelp: %llX\n", (int64_t)kCGEventFlagMaskHelp);
printf("kCGEventFlagMaskSecondaryFn: %llX\n", (int64_t)kCGEventFlagMaskSecondaryFn);
printf("kCGEventFlagMaskNumericPad: %llX\n", (int64_t)kCGEventFlagMaskNumericPad);
printf("kCGEventFlagMaskNonCoalesced: %llX\n", (int64_t)kCGEventFlagMaskNonCoalesced);
// sticky Fn, after clicking Home.
simulate_key(source, kVK_Home, true);
simulate_key(source, kVK_Home, false);
printf("\n\nSimulate h after Home.\n");
fflush(stdout);
// simulate_key(source, kVK_Shift, true);
// Simulate h. The behavior seems Fn + h.
simulate_key(source, kVK_ANSI_H, true);
simulate_key(source, kVK_ANSI_H, false);
// simulate_key(source, kVK_Shift, false);
// So as simulating e and d...
CFRelease(source);
}
int main(int argc, const char * argv[]) {
// UInt8 keyboard_type = LMGetKbdType();
// unsigned int layout_type = KBGetLayoutType(keyboard_type);
// printf("LMGetKbdType(): %d, KBGetLayoutType(): %d\n", keyboard_type, layout_type);
print33();
return 0;
}
我也遇到了同样的问题。并且您在研究过程中走向了正确的方向(检查是否设置了
kCGEventFlagMaskSecondaryFn
标志)。
所以解决方案是确保在调用之前没有设置任何标志 CGEventPost(kCGSessionEventTap, event);
只需在
CGEventPost
调用之前添加一行:
CGEventSetFlags(event, 0);
之后它会按预期工作。
CGEventRef event = CGEventCreateKeyboardEvent(source, key, key_down);
CGEventSetFlags(event, 0);
CGEventPost(kCGSessionEventTap, event);
CFRelease(event);