您的位置:首页 > 其它

OSX监听全局键盘按下事件并捕获事件源的硬件接口位置

2017-09-16 15:18 746 查看
在OSX系统全局监听键盘的按下事件,并可以捕获事件源的硬件的接口位置,用于区分是哪个键盘产生的事件。下面的代码只是以键盘为例子,其实是可以适用于其他输入外设的。如有需要可搜索相关外设的匹配字典的创建代码。

设备匹配字典

CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage,  UInt32 usage )
{
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
kCFAllocatorDefault, 0
, & kCFTypeDictionaryKeyCallBacks
, & kCFTypeDictionaryValueCallBacks );
if ( ! dict )
return NULL;

CFNumberRef pageNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, & usagePage );
if ( ! pageNumberRef ) {
CFRelease( dict );
return NULL;
}

CFDictionarySetValue( dict, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef );
CFRelease( pageNumberRef );

CFNumberRef usageNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, & usage );

if ( ! usageNumberRef ) {
CFRelease( dict );
return NULL;
}

CFDictionarySetValue( dict, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef );
CFRelease( usageNumberRef );

return dict;
}


事件的回调函数

void myHIDKeyboardCallback(void* context,  IOReturn result,  void* sender,  IOHIDValueRef value )
{
//get device product id and vendor id
IOHIDDeviceRef device = sender;
//    int32_t pid = 1;
//    CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberSInt32Type, &pid);
//    int32_t vendorID = 0;
//    CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberSInt32Type, &vendorID);
//    NSLog(@"vendor:%d product:%d", vendorID, pid);

IOHIDElementRef elem = IOHIDValueGetElement( value );

//    if (IOHIDElementGetUsagePage(elem) != 0x07)
//        return;

uint32_t scancode = IOHIDElementGetUsage( elem );

if (scancode < 3 || scancode > 231)
return;

int32_t locationID = 0;
CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey)), kCFNumberSInt32Type, &locationID);
NSLog(@"location:%d", locationID);

long pressed = IOHIDValueGetIntegerValue( value );
uint64_t timestamp =  IOHIDValueGetTimeStamp(value);
printf( "scancode: %3d, %s timestamp:%llu \n", scancode, pressed?"keydown":"keyup  ", timestamp);

//send the keyboard event
NSDictionary* userInfo = [[NSDictionary alloc]initWithObjectsAndKeys:
[NSNumber numberWithInt:scancode], NOTIFICATION_KEY_ScanCode,
[NSNumber numberWithInt:locationID], NOTIFICATION_KEY_Location,
[NSNumber numberWithLong:pressed], NOTIFICATION_KEY_IsKeyDown,
[NSNumber numberWithLong:timestamp], NOTIFICATION_KEY_Timestamp, nil];
NSNotification* notification = [NSNotification notificationWithName:NOTIFICATION_KeyBoardEvent object:nil userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:notification];

UsbSignalController* controller = (__bridge UsbSignalController*)context;
[controller onKeyEvent:scancode Location:locationID IsDown:pressed Timestamp:timestamp];
}


注册键盘钩子

-(void)registerKeyboardHook
{
IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone );

CFMutableDictionaryRef keyboard = myCreateDeviceMatchingDictionary( 0x01, 6 );
CFArrayRef matches;
{
//CFMutableDictionaryRef keypad   = myCreateDeviceMatchingDictionary( 0x01, 7 );
CFMutableDictionaryRef matchesList[] = { keyboard/*, keypad*/ };
matches = CFArrayCreate( kCFAllocatorDefault, (const void **)matchesList, 1/*2*/, NULL );
}

IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches );
CFRelease(matches);
CFRelease(keyboard );

IOHIDManagerRegisterInputValueCallback(hidManager, myHIDKeyboardCallback, (__bridge void*)self);
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode );
IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone );
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: