鼠标IOHIDDeviceRef在macOS 10.12中未提供任何输入报告

Jus*_*Sid 8 c macos iokit

我正在尝试接收鼠标的输入报告(用包裹IOHIDDeviceRef),但是对于我来说,我似乎无法在macOS 10.12上使用它。相同的代码在10.11和10.10中都可以正常工作,并且对所有其他类型的HID输入设备(键盘,游戏手柄和操纵杆)都适用。

我已经尝试了多种方法,但是无论如何,我只是没有收到任何输入事件。我试过了:

IOHIDDeviceRegisterInputReportCallbackIOHIDDeviceRegisterInputValueCallback(),因为它们是接收日期的最直接的方法。另外,我尝试创建一个添加IOHIDQueueRef了所有IOHIDElement鼠标的的。

这些方法都不能解决问题。如前所述,该代码确实适用于其他输入设备,因此我确定自己正确设置了99.999%。我打开通过IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone)它返回的设备kIOReturnSuccess。我将设备安排在具有kCFRunLoopCommonModes模式的主运行循环中。在IOHIDQueueRefI 的情况下,我还将那个注册到运行循环并调用IOHIDQueueStart()。同样值得注意的是:该代码曾经在10.10和10.11上运行,只是停止了10.12的工作。

我在这里做错了,还是macOS 10.12不再支持此功能?

这是一个最小的repro示例(为样板鳕鱼道歉),它将与键盘和鼠标设备匹配并随后打开。但是,它只会为键盘产生输入值,鼠标不会在10.12上报告任何内容:

#include <iostream>
#include <IOKit/hid/IOHIDLib.h>

void HIDDeviceValueReceived(__unused void *context, __unused IOReturn result, void *sender, __unused IOHIDValueRef value)
{
    std::cout << "Received IOHIDValue from " << sender << std::endl;
}

void HIDDeviceMatched(__unused void *context, __unused IOReturn result, __unused void *sender, IOHIDDeviceRef deviceRef)
{
    CFNumberRef usagePageValue = (CFNumberRef)IOHIDDeviceGetProperty(deviceRef, CFSTR(kIOHIDPrimaryUsagePageKey));
    CFNumberRef usageValue = (CFNumberRef)IOHIDDeviceGetProperty(deviceRef, CFSTR(kIOHIDPrimaryUsageKey));

    if(!usagePageValue || !usageValue)
    {
        IOHIDDeviceClose(deviceRef, kIOHIDOptionsTypeNone);
        return;
    }

    int32_t usagePage;
    int32_t usage;

    CFNumberGetValue(usagePageValue, kCFNumberSInt32Type, &usagePage);
    CFNumberGetValue(usageValue, kCFNumberSInt32Type, &usage);

    switch(usagePage)
    {
        case kHIDPage_GenericDesktop:
        {
            switch(usage)
            {
                case kHIDUsage_GD_Keyboard:
                case kHIDUsage_GD_Keypad:
                {
                    std::cout << "Found keyboard device " << (void *)deviceRef << std::endl;

                    if(IOHIDDeviceOpen(deviceRef, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
                        std::cerr << "Couldn't open keyboard device";

                    IOHIDDeviceRegisterInputValueCallback(deviceRef, &HIDDeviceValueReceived, nullptr);
                    IOHIDDeviceScheduleWithRunLoop(deviceRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
                    break;
                }

                case kHIDUsage_GD_Mouse:
                case kHIDUsage_GD_Pointer:
                {
                    std::cout << "Found mouse device " << (void *)deviceRef << std::endl;

                    if(IOHIDDeviceOpen(deviceRef, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
                        std::cerr << "Couldn't open mouse device";

                    IOHIDDeviceRegisterInputValueCallback(deviceRef, &HIDDeviceValueReceived, nullptr);
                    IOHIDDeviceScheduleWithRunLoop(deviceRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode);

                    break;
                }

                default:
                    break;
            }


            break;
        }

        default:
            break;
    }
}

int main()
{
    // Find all HID Devices
    IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
    IOHIDManagerSetDeviceMatching(hidManager, nullptr);

    IOHIDManagerRegisterDeviceMatchingCallback(hidManager, &HIDDeviceMatched, nullptr);

    IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
    IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);

    // Run the run loop
    CFRunLoopRun();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:CGEventTaps仍然可以正常工作,所以我认为这不是安全的事情。我想我会就此向苹果提交错误报告。