如何在OSX中点击/挂接键盘事件并记录每个事件触发哪个键盘 [英] How to tap/hook keyboard events in OSX and record which keyboard fires each event

查看:299
本文介绍了如何在OSX中点击/挂接键盘事件并记录每个事件触发哪个键盘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在发现了如何在低级上钩挂/敲击OS X上的键盘事件:

I've now discovered how to hook/tap keyboard events on OS X at a low level: How to tap (hook) F7 through F12 and Power/Eject on a MacBook keyboard

从该答案中打印出代码:

Printing out the code from that answer:

// compile and run from the commandline with:
//    clang  -framework coreFoundation  -framework IOKit  ./HID.c  -o hid
//    sudo ./hid

// This code works with the IOHID library to get notified of keys.
//   Still haven't figured out how to truly intercept with
//   substitution.

#include <IOKit/hid/IOHIDValue.h>
#include <IOKit/hid/IOHIDManager.h>

void myHIDKeyboardCallback( void* context,  IOReturn result,  void* sender,  IOHIDValueRef value )
{
    IOHIDElementRef elem = IOHIDValueGetElement( value );

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

    uint32_t scancode = IOHIDElementGetUsage( elem );

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

    long pressed = IOHIDValueGetIntegerValue( value );

    printf( "scancode: %d, pressed: %ld\n", scancode, pressed );
}


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;
}


int main(void)
{
    IOHIDManagerRef hidManager = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );

    CFArrayRef matches;
    {
        CFMutableDictionaryRef keyboard = myCreateDeviceMatchingDictionary( 0x01, 6 );
        CFMutableDictionaryRef keypad   = myCreateDeviceMatchingDictionary( 0x01, 7 );

        CFMutableDictionaryRef matchesList[] = { keyboard, keypad };

        matches = CFArrayCreate( kCFAllocatorDefault, (const void **)matchesList, 2, NULL );
    }

    IOHIDManagerSetDeviceMatchingMultiple( hidManager, matches );

    IOHIDManagerRegisterInputValueCallback( hidManager, myHIDKeyboardCallback, NULL );

    IOHIDManagerScheduleWithRunLoop( hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode );

    IOHIDManagerOpen( hidManager, kIOHIDOptionsTypeNone );

    CFRunLoopRun(); // spins
}

我如何(也许改编代码)来识别哪个键盘负责特定事件?

How can I (maybe adapt that code to) identify which keyboard is responsible for a particular event?

用例是我计划使用将重新映射的外部键盘,但同时保留我内置的MacBook键盘的原始映射.

The use case is that I am planning to use an external keyboard which will be remapped, but at the same time retaining the original mapping for my inbuilt MacBook keyboard.


用于辅助键盘的OSX HID过滤器?
https://github.com/candera/khordr/blob/master/src/c/keygrab/hid-scratch.c
http://ianjoker.googlecode.com/svn/trunk/Joker/小丑/hid_test.cpp
> http://www.cplusplusdevelop.com/72_17345226/
http://www.cocoabuilder.com/archive/cocoa/229902-which-keyboard-barcode-scanner-did-the-event-come-from.html


OSX HID Filter for Secondary Keyboard?
https://github.com/candera/khordr/blob/master/src/c/keygrab/hid-scratch.c
http://ianjoker.googlecode.com/svn/trunk/Joker/Joker/hid_test.cpp
http://www.cplusplusdevelop.com/72_17345226/
http://www.cocoabuilder.com/archive/cocoa/229902-which-keyboard-barcode-scanner-did-the-event-come-from.html

推荐答案

我正在研究此问题,终于得到了解决方案. OP的代码正确,如果您想要键盘/键盘的产品ID,请在myHIDKeyboardCallback()函数中添加行:

I was working on this problem, and finally got the solution. OP's code is correct, if you'd like the product ID of the keyboard/pad, add lines to the myHIDKeyboardCallback() function:

void myHIDKeyboardCallback(void* context,  IOReturn result,  void* sender,  IOHIDValueRef value){

    IOHIDElementRef elem = IOHIDValueGetElement(value);
    if (IOHIDElementGetUsagePage(elem) != 0x07)
        return;

    IOHIDDeviceRef device = sender;
    int32_t pid = 1;
    CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR("idProduct")), kCFNumberSInt32Type, &pid);

    uint32_t scancode = IOHIDElementGetUsage(elem);

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

    long pressed = IOHIDValueGetIntegerValue(value);

    printf("scancode: %d, pressed: %ld, keyboardId=%d\n", scancode, pressed, pid);
}

就像@pmdj所说的,您可以使用IOHIDDeviceRegisterInputValueCallback()一样,我对此感到很麻烦,并且发现sender参数仍然提供了键盘产品ID.

As @pmdj said you can use IOHIDDeviceRegisterInputValueCallback(), I was having trouble with this, and found that sender argument provided keyboard product id anyways.

这篇关于如何在OSX中点击/挂接键盘事件并记录每个事件触发哪个键盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆