dos*_*nde 8 keyboard macos iokit core-foundation
我正在尝试使用IOHIDManager获取修饰键事件,因为Cocoa flagsChanged事件缺乏(难以区分按下/释放,左/右如果两者都关闭等)这里是我创建管理器并注册回调的代码.
IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
if (CFGetTypeID(hidManager) != IOHIDManagerGetTypeID())
return 1;
CFMutableDictionaryRef capsLock =
myCreateDeviceMatchingDictionary(0x07, 0x39);
CFMutableDictionaryRef lctrl =
myCreateDeviceMatchingDictionary(0x07, 0xE0);
CFMutableDictionaryRef lshift =
myCreateDeviceMatchingDictionary(0x07, 0xE1);
CFMutableDictionaryRef lalt =
myCreateDeviceMatchingDictionary(0x07, 0xE2);
CFMutableDictionaryRef lsuper =
myCreateDeviceMatchingDictionary(0x07, 0xE3);
CFMutableDictionaryRef rctrl =
myCreateDeviceMatchingDictionary(0x07, 0xE4);
CFMutableDictionaryRef rshift =
myCreateDeviceMatchingDictionary(0x07, 0xE5);
CFMutableDictionaryRef ralt =
myCreateDeviceMatchingDictionary(0x07, 0xE6);
CFMutableDictionaryRef rsuper =
myCreateDeviceMatchingDictionary(0x07, 0xE7);
CFMutableDictionaryRef matchesList[] = {
capsLock,
lctrl,
lshift,
lalt,
lsuper,
rctrl,
rshift,
ralt,
rsuper
};
CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault,
(const void **)matchesList, 9, NULL);
IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches);
IOHIDManagerRegisterInputValueCallback(hidManager,
myHandleModifiersCallback, NULL);
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(),
kCFRunLoopDefaultMode);
IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);
Run Code Online (Sandbox Code Playgroud)
但是,回调永远不会运行.我错过了什么吗?
我不完全了解HID使用页面,因此我不知道是否将通用桌面页面(0x01)与键盘使用ID(06)或键盘/键盘页面(0x07)与个人的使用ID一起使用键.也许这与它有关?
dos*_*nde 10
我想到了.这样做的方法是使用通用桌面页面(0x01)键盘(06)(和键盘(07)的完整性)与IOHIDManagerSetDeviceMatchingMultiple一起使用,然后输入值回调获取键盘/键盘用法页面(0x07)的东西.
例如,要为所有键盘/键盘设置HIDManager,可以执行以下操作:
IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
CFMutableDictionaryRef keyboard =
myCreateDeviceMatchingDictionary(0x01, 6);
CFMutableDictionaryRef keypad =
myCreateDeviceMatchingDictionary(0x01, 7);
CFMutableDictionaryRef matchesList[] = {
keyboard,
keypad,
};
CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault,
(const void **)matchesList, 2, NULL);
IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches);
IOHIDManagerRegisterInputValueCallback(hidManager,
myHIDKeyboardCallback, NULL);
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(),
kCFRunLoopDefaultMode);
IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);
Run Code Online (Sandbox Code Playgroud)
myCreateDeviceMatchingDictionary的位置如下:
CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage,
UInt32 usage) {
CFMutableDictionaryRef ret = CFDictionaryCreateMutable(kCFAllocatorDefault,
0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!ret)
return NULL;
CFNumberRef pageNumberRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberIntType, &usagePage );
if (!pageNumberRef) {
CFRelease(ret);
return NULL;
}
CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef);
CFRelease(pageNumberRef);
CFNumberRef usageNumberRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberIntType, &usage);
if (!usageNumberRef) {
CFRelease(ret);
return NULL;
}
CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef);
CFRelease(usageNumberRef);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
myHIDKeyboardCallback类似于:
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);
// ... Do something ...
}
Run Code Online (Sandbox Code Playgroud)
请注意,每次按下或释放时,回调似乎被调用多次,但使用ID超出正常范围,这就是"if(scancode <4 || scancode> 231)"的用途.
感谢您提供问题的答案。
代替检查scancode <4 或scancode >231 的myHIDKeyboardCallback中的 if 语句,您可以使用IOHIDManagerSetInputValueMatching。
// before IOHIDManagerOpen
int usageMin = 4;
CFNumberRef minNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usageMin);
CFDictionarySetValue(inputValueFilter, CFSTR(kIOHIDElementUsageMinKey), minNumberRef);
CFRelease(minNumberRef);
int usageMax = 231;
CFNumberRef maxNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usageMax);
CFDictionarySetValue(inputValueFilter, CFSTR(kIOHIDElementUsageMaxKey), maxNumberRef);
CFRelease(maxNumberRef);
IOHIDManagerSetInputValueMatching(hidManager, inputValueFilter);
Run Code Online (Sandbox Code Playgroud)
它更多的是 LOC 而不是一个简单的 if 语句,但你最终会得到一个更清晰的回调。
归档时间: |
|
查看次数: |
4515 次 |
最近记录: |