因此,我尝试使用CGL和IOHIDManager组合一个简单的全屏OpenGL应用程序,以便学习低级API。目前,我正在创建一个OpenGL上下文并全屏启动它。我现在尝试添加键盘输入,以便我可以退出应用程序。我发现了许多使用IOHIDManager读取密钥的类似例子,但无论我做什么,我的回调都不会触发。
我的回调只是一个打印" here"的函数。我不确定自己哪里出错了 - 我已经尝试了CFRunLoopGetCurrent()和CFRunLoopMain()。我的主要是一个while循环。是什么给了什么?
CFMutableDictionaryRef CreateMatchingDictionary(UInt32 usage_page, UInt32 usage) {
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFNumberRef page_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page);
CFDictionarySetValue(dictionary, CFSTR(kIOHIDDeviceUsagePageKey), page_number);
CFRelease(page_number);
CFNumberRef usage_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
CFDictionarySetValue(dictionary, CFSTR(kIOHIDDeviceUsageKey), usage_number);
CFRelease(usage_number);
return dictionary;
}
void CreateInputManager() {
IOHIDManagerRef hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
IOHIDManagerSetDeviceMatching(hid_manager, matching_dictionary);
IOHIDManagerRegisterInputValueCallback(hid_manager, KeyboardCallback, NULL);
IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
void KeyboardCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
puts("CALLBACK!");
}
int main() {
// Commented out CGL context & fullscreen window creation
CreateInputManager();
while(true) {
;
}
}
更新
如果我将CFRunLoopRun()放在函数CreateInputManager的末尾,则调用我的回调,但函数永远不会返回。这应该如何在单线程CGL应用程序中工作?是否严格要求IOHIDManager要求运行循环才能运行?
答案 0 :(得分:1)
IOKit和HID通过Mach消息传递,而后者又与runloop机制深度集成,正如您所发现的那样。如果您确实想要进行繁忙轮询,可以使用CFRunLoopRunInMode
函数并使用零超时来检查事件。
您可能希望考虑使用CVDisplayLink在每次垂直帧刷新时调用渲染代码。将从runloop调用显示链接的回调,因此您可以使主线程在CFRunLoopRun()中运行。
请参阅https://developer.apple.com/library/mac/qa/qa1385/_index.html,了解Apple建议您如何在OpenGL应用程序中构建事件处理。
答案 1 :(得分:0)
结果我需要使用CreateInputManager
函数创建一个单独的pthread,指定IOHIDManager在CFRunLoopGetCurrent()
上安排回调并通过调用{{1}启动该线程上的运行循环}}
我想知道是否有办法让IOHIDManager使用普通的轮询而不是这些回调......