zoukankan      html  css  js  c++  java
  • OSX监听全局键盘按下事件并捕获事件源的硬件接口位置

    在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 
    ", 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 );
    }
  • 相关阅读:
    国际组织
    波段
    hhgis驱动
    百度地图格式
    气象数据格式
    汽车用传感器
    无线传感器网络
    【系统软件工程师面试】7. 消息队列
    【ToDo】存储设计概述
    Arthas: Java 动态追踪技术
  • 原文地址:https://www.cnblogs.com/keitsi/p/7531408.html
Copyright © 2011-2022 走看看