我的目标是使用 IOHID 阻止按键到达操作系统(由于其他原因不能使用 CGEvent)。根据 kIOHIDOptionsTypeSeizeDevice 的文档:用于打开独占通信...
我的目标是使用 IOHID 阻止按键到达操作系统(由于其他原因不能使用 CGEvent)。根据 的文档 kIOHIDOptionsTypeSeizeDevice
:
用于打开与设备的独占通信。这将阻止系统和其他客户端接收来自设备的事件。
#import "TestKeys.h"
#import <IOKit/hid/IOHIDManager.h>
#import <IOKit/hid/IOHIDUsageTables.h>
@implementation TestKeys
#define KEYS 2
static void Handle_InputCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef value)
{
IOHIDElementRef elem = IOHIDValueGetElement(value);
uint16_t scancode = IOHIDElementGetUsage(elem);
if (scancode < 4 || scancode > 231) {
return;
}
NSLog(@"Key event received: %d", scancode);
}
static void Handle_DeviceMatchingCallback(void * inContext, IOReturn inResult, void * inSender, IOHIDDeviceRef inIOHIDDeviceRef)
{
NSLog(@"Connected");
}
static void Handle_RemovalCallback(void * inContext, IOReturn inResult, void * inSender, IOHIDDeviceRef inIOHIDDeviceRef)
{
NSLog(@"Removed");
}
-(void)start
{
IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone);
if (CFGetTypeID(manager) != IOHIDManagerGetTypeID()) {
exit(1);
}
int usagePage = kHIDPage_GenericDesktop;
int usage = kHIDUsage_GD_Keyboard;
CFStringRef keys[KEYS] = {
CFSTR(kIOHIDDeviceUsagePageKey),
CFSTR(kIOHIDDeviceUsageKey),
};
CFNumberRef values[KEYS] = {
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usagePage),
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usage),
};
CFDictionaryRef matchingDict = CFDictionaryCreate(kCFAllocatorDefault,
(const void **) keys, (const void **) values, KEYS,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
for (int i=0; i<KEYS; i++) {
CFRelease(keys[i]);
CFRelease(values[i]);
}
IOHIDManagerSetDeviceMatching(manager, matchingDict);
CFRelease(matchingDict);
IOHIDManagerRegisterDeviceMatchingCallback(manager, Handle_DeviceMatchingCallback, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(manager, Handle_RemovalCallback, NULL);
IOHIDManagerRegisterInputValueCallback(manager, Handle_InputCallback, NULL);
IOHIDManagerOpen(manager, kIOHIDOptionsTypeSeizeDevice);
IOHIDManagerScheduleWithRunLoop(manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
@end
该代码运行并设法从操作系统全局查看和打印所有击键,但它似乎 kIOHIDOptionsTypeSeizeDevice
被忽略了,因为击键仍然被传递给 macOS。
编辑: 添加 IOReturn result =
到代码中会暴露错误 -536870207
,该错误转换为 kIOReturnNotPrivileged
。然后我将 Xcode 方案更改为 root 并能够阻止键盘按键。
这就引出了我的下一个问题,我怎样才能将此代码添加到显然不以 root 权限运行的开发者 ID 应用程序中?