17#if defined(__APPLE__) && !defined(CPPPARSER)
20(
"iokit-scan-mouse-devices",
false,
21 PRC_DESC(
"Set this to true to enable capturing raw mouse data via IOKit on "
22 "macOS. This is disabled by default because newer macOS versions "
23 "will prompt the user explicitly for permissions when this is on."));
26(
"iokit-scan-keyboard-devices",
false,
27 PRC_DESC(
"Set this to true to enable capturing raw keyboard data via IOKit on "
28 "macOS. This is disabled by default because newer macOS versions "
29 "will prompt the user explicitly for permissions when this is on."));
36IOKitInputDeviceManager::
37IOKitInputDeviceManager() {
38 _hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
41 <<
"Failed to create an IOHIDManager.\n";
46 int page = kHIDPage_GenericDesktop;
47 int usages[] = {kHIDUsage_GD_GamePad,
48 kHIDUsage_GD_Joystick,
49 kHIDUsage_GD_MultiAxisController,
53 if (iokit_scan_mouse_devices) {
54 usages[num_usages++] = kHIDUsage_GD_Mouse;
56 if (iokit_scan_keyboard_devices) {
57 usages[num_usages++] = kHIDUsage_GD_Keyboard;
62 CFMutableArrayRef match = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
66 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
67 CFNumberRef page_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
68 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), page_ref);
70 CFNumberRef usage_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, usage);
71 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), usage_ref);
73 CFArrayAppendValue(match, dict);
77 IOHIDManagerSetDeviceMatchingMultiple(_hid_manager, match);
80 IOHIDManagerRegisterDeviceMatchingCallback(_hid_manager, on_match_device,
this);
81 IOHIDManagerRegisterDeviceRemovalCallback(_hid_manager, on_remove_device,
this);
82 IOHIDManagerScheduleWithRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
83 IOHIDManagerOpen(_hid_manager, kIOHIDOptionsTypeNone);
89IOKitInputDeviceManager::
90~IOKitInputDeviceManager() {
91 IOHIDManagerUnscheduleFromRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
92 IOHIDManagerClose(_hid_manager, kIOHIDOptionsTypeNone);
93 CFRelease(_hid_manager);
99void IOKitInputDeviceManager::
100on_match_device(
void *ctx, IOReturn result,
void *sender, IOHIDDeviceRef device) {
101 IOKitInputDeviceManager *mgr = (IOKitInputDeviceManager *)ctx;
102 nassertv(mgr !=
nullptr);
105 IOKitInputDevice *input_device =
new IOKitInputDevice(device);
106 if (device_cat.is_debug()) {
108 <<
"Discovered input device " << *input_device <<
"\n";
110 mgr->add_device(input_device);
111 mgr->_devices_by_hidref[device] = input_device;
117void IOKitInputDeviceManager::
118on_remove_device(
void *ctx, IOReturn result,
void *sender, IOHIDDeviceRef device) {
119 IOKitInputDeviceManager *mgr = (IOKitInputDeviceManager *)ctx;
120 nassertv(mgr !=
nullptr);
123 auto it = mgr->_devices_by_hidref.find(device);
124 nassertv(it != mgr->_devices_by_hidref.end());
125 IOKitInputDevice *input_device = it->second;
127 input_device->set_connected(
false);
129 mgr->_devices_by_hidref.erase(device);
131 IOHIDDeviceClose(device, kIOHIDOptionsTypeNone);
133 if (device_cat.is_debug()) {
135 <<
"Removed input device " << *input_device <<
"\n";
138 mgr->remove_device(input_device);
This is a convenience class to specialize ConfigVariable as a boolean type.