diff --git a/panda/src/device/inputDeviceManager.cxx b/panda/src/device/inputDeviceManager.cxx index a4ee1c4c8e..140b4379f1 100644 --- a/panda/src/device/inputDeviceManager.cxx +++ b/panda/src/device/inputDeviceManager.cxx @@ -12,77 +12,21 @@ */ #include "inputDeviceManager.h" -#include "ioKitInputDevice.h" +#include "ioKitInputDeviceManager.h" #include "linuxInputDeviceManager.h" #include "winInputDeviceManager.h" #include "throw_event.h" -InputDeviceManager *InputDeviceManager::_global_ptr = NULL; +InputDeviceManager *InputDeviceManager::_global_ptr = nullptr; /** * Initializes the input device manager by scanning which devices are currently * connected and setting up any platform-dependent structures necessary for * listening for future device connect events. */ -#if defined(__APPLE__) -InputDeviceManager:: -InputDeviceManager() { - _hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (!_hid_manager) { - device_cat.error() - << "Failed to create an IOHIDManager.\n"; - return; - } - - // The types of devices we're interested in. - int page = kHIDPage_GenericDesktop; - int usages[] = {kHIDUsage_GD_GamePad, - kHIDUsage_GD_Joystick, - kHIDUsage_GD_Mouse, - kHIDUsage_GD_Keyboard, - kHIDUsage_GD_MultiAxisController, 0}; - int *usage = usages; - - // This giant mess is necessary to create an array of match dictionaries - // that will match the devices we're interested in. - CFMutableArrayRef match = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - nassertv(match); - while (*usage) { - CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFNumberRef page_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); - CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), page_ref); - CFRelease(page_ref); - CFNumberRef usage_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, usage); - CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), usage_ref); - CFRelease(usage_ref); - CFArrayAppendValue(match, dict); - CFRelease(dict); - ++usage; - } - IOHIDManagerSetDeviceMatchingMultiple(_hid_manager, match); - CFRelease(match); - - IOHIDManagerRegisterDeviceMatchingCallback(_hid_manager, on_match_device, this); - IOHIDManagerScheduleWithRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes); - IOHIDManagerOpen(_hid_manager, kIOHIDOptionsTypeNone); -} -#else InputDeviceManager:: InputDeviceManager() : _lock("InputDeviceManager") { } -#endif - -/** - * Closes any resources that the device manager was using to listen for events. - */ -InputDeviceManager:: -~InputDeviceManager() { -#if defined(__APPLE__) - IOHIDManagerUnscheduleFromRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes); - IOHIDManagerClose(_hid_manager, kIOHIDOptionsTypeNone); - CFRelease(_hid_manager); -#endif -} /** * Creates the global input manager. @@ -91,6 +35,8 @@ void InputDeviceManager:: make_global_ptr() { #ifdef _WIN32 _global_ptr = new WinInputDeviceManager; +#elif defined(__APPLE__) + _global_ptr = new IOKitInputDeviceManager; #elif defined(PHAVE_LINUX_INPUT_H) _global_ptr = new LinuxInputDeviceManager; #else diff --git a/panda/src/device/inputDeviceManager.h b/panda/src/device/inputDeviceManager.h index 5f827cd3a9..8fae76c2d1 100644 --- a/panda/src/device/inputDeviceManager.h +++ b/panda/src/device/inputDeviceManager.h @@ -24,10 +24,6 @@ class WinRawInputDevice; #endif -#ifdef __APPLE__ -#include -#endif - /** * This class keeps track of all the devices on a system, and sends out events * when a device has been hot-plugged. @@ -35,15 +31,9 @@ class WinRawInputDevice; class EXPCL_PANDA_DEVICE InputDeviceManager { protected: InputDeviceManager(); - ~InputDeviceManager(); static void make_global_ptr(); -#ifdef PHAVE_LINUX_INPUT_H - InputDevice *consider_add_evdev_device(int index); - InputDevice *consider_add_js_device(int index); -#endif - PUBLISHED: InputDeviceSet get_devices() const; InputDeviceSet get_devices(InputDevice::DeviceClass device_class) const; @@ -65,12 +55,6 @@ protected: InputDeviceSet _inactive_devices; #endif -#if defined(__APPLE__) && !defined(CPPPARSER) - IOHIDManagerRef _hid_manager; - - static void on_match_device(void *ctx, IOReturn result, void *sender, IOHIDDeviceRef device); -#endif - InputDeviceSet _connected_devices; static InputDeviceManager *_global_ptr; diff --git a/panda/src/device/ioKitInputDeviceManager.cxx b/panda/src/device/ioKitInputDeviceManager.cxx new file mode 100644 index 0000000000..6874d9baba --- /dev/null +++ b/panda/src/device/ioKitInputDeviceManager.cxx @@ -0,0 +1,93 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file ioKitInputDeviceManager.cxx + * @author rdb + * @date 2018-02-04 + */ + +#include "ioKitInputDeviceManager.h" +#include "ioKitInputDevice.h" + +#if defined(__APPLE__) && !defined(CPPPARSER) + +/** + * Initializes the input device manager by scanning which devices are currently + * connected and setting up any platform-dependent structures necessary for + * listening for future device connect events. + */ +IOKitInputDeviceManager:: +IOKitInputDeviceManager() { + _hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (!_hid_manager) { + device_cat.error() + << "Failed to create an IOHIDManager.\n"; + return; + } + + // The types of devices we're interested in. + int page = kHIDPage_GenericDesktop; + int usages[] = {kHIDUsage_GD_GamePad, + kHIDUsage_GD_Joystick, + kHIDUsage_GD_Mouse, + kHIDUsage_GD_Keyboard, + kHIDUsage_GD_MultiAxisController, 0}; + int *usage = usages; + + // This giant mess is necessary to create an array of match dictionaries + // that will match the devices we're interested in. + CFMutableArrayRef match = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + nassertv(match); + while (*usage) { + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFNumberRef page_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); + CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), page_ref); + CFRelease(page_ref); + CFNumberRef usage_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, usage); + CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), usage_ref); + CFRelease(usage_ref); + CFArrayAppendValue(match, dict); + CFRelease(dict); + ++usage; + } + IOHIDManagerSetDeviceMatchingMultiple(_hid_manager, match); + CFRelease(match); + + IOHIDManagerRegisterDeviceMatchingCallback(_hid_manager, on_match_device, this); + IOHIDManagerScheduleWithRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes); + IOHIDManagerOpen(_hid_manager, kIOHIDOptionsTypeNone); +} + +/** + * Closes any resources that the device manager was using to listen for events. + */ +IOKitInputDeviceManager:: +~IOKitInputDeviceManager() { + IOHIDManagerUnscheduleFromRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes); + IOHIDManagerClose(_hid_manager, kIOHIDOptionsTypeNone); + CFRelease(_hid_manager); +} + +/** + * Called by IOKit when an input device matching our filters has been found. + */ +void IOKitInputDeviceManager:: +on_match_device(void *ctx, IOReturn result, void *sender, IOHIDDeviceRef device) { + InputDeviceManager *mgr = (InputDeviceManager *)ctx; + nassertv(mgr != nullptr); + nassertv(device); + + PT(InputDevice) input_device = new IOKitInputDevice(device); + if (device_cat.is_debug()) { + device_cat.debug() + << "Discovered input device " << *input_device << "\n"; + } + mgr->add_device(input_device); +} + +#endif diff --git a/panda/src/device/ioKitInputDeviceManager.h b/panda/src/device/ioKitInputDeviceManager.h new file mode 100644 index 0000000000..788413e1b0 --- /dev/null +++ b/panda/src/device/ioKitInputDeviceManager.h @@ -0,0 +1,40 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file ioKitInputDeviceManager.h + * @author rdb + * @date 2018-02-04 + */ + +#ifndef IOKITINPUTDEVICEMANAGER_H +#define IOKITINPUTDEVICEMANAGER_H + +#include "inputDeviceManager.h" + +#if defined(__APPLE__) && !defined(CPPPARSER) +#include + +/** + * The macOS implementation of InputDeviceManager. + */ +class EXPCL_PANDA_DEVICE IOKitInputDeviceManager FINAL : public InputDeviceManager { +protected: + IOKitInputDeviceManager(); + ~IOKitInputDeviceManager(); + +protected: + IOHIDManagerRef _hid_manager; + + static void on_match_device(void *ctx, IOReturn result, void *sender, IOHIDDeviceRef device); + + friend class InputDeviceManager; +}; + +#endif + +#endif diff --git a/panda/src/device/p3device_composite1.cxx b/panda/src/device/p3device_composite1.cxx index 0067579474..6e7da5b78b 100644 --- a/panda/src/device/p3device_composite1.cxx +++ b/panda/src/device/p3device_composite1.cxx @@ -11,6 +11,7 @@ #include "inputDeviceNode.cxx" #include "inputDeviceSet.cxx" #include "ioKitInputDevice.cxx" +#include "ioKitInputDeviceManager.cxx" #include "linuxInputDeviceManager.cxx" #include "linuxJoystickDevice.cxx" #include "winInputDeviceManager.cxx"