summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface/OSX
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2013-12-07 15:14:29 -0500
committerJasper St. Pierre <jstpierre@mecheye.net>2013-12-31 14:03:19 -0500
commit34692ab826abc8f8faa61bdb2280b742424528f1 (patch)
treeb0eedc645badbea316ff59c125eaf808b28777ec /Source/Core/InputCommon/ControllerInterface/OSX
parent43e618682e8093602fc83dfa902ee7ae3fd3a4f6 (diff)
Remove unnecessary Src/ folders
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface/OSX')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSX.h16
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm213
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h80
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm274
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h71
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.mm276
6 files changed, 930 insertions, 0 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h
new file mode 100644
index 0000000000..a922e3f2dd
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "../Device.h"
+
+namespace ciface
+{
+namespace OSX
+{
+
+void Init(std::vector<Core::Device*>& devices, void *window);
+void DeInit();
+
+void DeviceElementDebugPrint(const void *, void *);
+
+}
+}
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm
new file mode 100644
index 0000000000..8a859f46c8
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm
@@ -0,0 +1,213 @@
+#include <Foundation/Foundation.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <Cocoa/Cocoa.h>
+
+#include "OSX.h"
+#include "OSXKeyboard.h"
+#include "OSXJoystick.h"
+
+#include <map>
+
+namespace ciface
+{
+namespace OSX
+{
+
+
+static IOHIDManagerRef HIDManager = NULL;
+static CFStringRef OurRunLoop = CFSTR("DolphinOSXInput");
+static std::map<std::string, int> kbd_name_counts, joy_name_counts;
+
+void DeviceElementDebugPrint(const void *value, void *context)
+{
+ IOHIDElementRef e = (IOHIDElementRef)value;
+ bool recurse = false;
+ if (context)
+ recurse = *(bool*)context;
+
+ std::string type = "";
+ switch (IOHIDElementGetType(e)) {
+ case kIOHIDElementTypeInput_Axis:
+ type = "axis";
+ break;
+ case kIOHIDElementTypeInput_Button:
+ type = "button";
+ break;
+ case kIOHIDElementTypeInput_Misc:
+ type = "misc";
+ break;
+ case kIOHIDElementTypeInput_ScanCodes:
+ type = "scancodes";
+ break;
+ case kIOHIDElementTypeOutput:
+ type = "output";
+ break;
+ case kIOHIDElementTypeFeature:
+ type = "feature";
+ break;
+ case kIOHIDElementTypeCollection:
+ type = "collection";
+ break;
+ }
+
+ std::string c_type = "";
+ if (type == "collection")
+ {
+ switch (IOHIDElementGetCollectionType(e)) {
+ case kIOHIDElementCollectionTypePhysical:
+ c_type = "physical";
+ break;
+ case kIOHIDElementCollectionTypeApplication:
+ c_type = "application";
+ break;
+ case kIOHIDElementCollectionTypeLogical:
+ c_type = "logical";
+ break;
+ case kIOHIDElementCollectionTypeReport:
+ c_type = "report";
+ break;
+ case kIOHIDElementCollectionTypeNamedArray:
+ c_type = "namedArray";
+ break;
+ case kIOHIDElementCollectionTypeUsageSwitch:
+ c_type = "usageSwitch";
+ break;
+ case kIOHIDElementCollectionTypeUsageModifier:
+ c_type = "usageModifier";
+ break;
+ }
+ }
+
+ c_type.append(" ");
+ NSLog(@"%s%s%spage: 0x%x usage: 0x%x name: %@ "
+ "lmin: %ld lmax: %ld pmin: %ld pmax: %ld",
+ type.c_str(),
+ type == "collection" ? ":" : "",
+ type == "collection" ? c_type.c_str() : " ",
+ IOHIDElementGetUsagePage(e),
+ IOHIDElementGetUsage(e),
+ IOHIDElementGetName(e), // usually just NULL
+ IOHIDElementGetLogicalMin(e),
+ IOHIDElementGetLogicalMax(e),
+ IOHIDElementGetPhysicalMin(e),
+ IOHIDElementGetPhysicalMax(e));
+
+ if ((type == "collection") && recurse)
+ {
+ CFArrayRef elements = IOHIDElementGetChildren(e);
+ CFRange range = {0, CFArrayGetCount(elements)};
+ // this leaks...but it's just debug code, right? :D
+ CFArrayApplyFunction(elements, range,
+ DeviceElementDebugPrint, NULL);
+ }
+}
+
+void DeviceDebugPrint(IOHIDDeviceRef device)
+{
+#if 0
+#define shortlog(x) NSLog(@"%s: %@", \
+ x, IOHIDDeviceGetProperty(device, CFSTR(x)));
+ NSLog(@"-------------------------");
+ NSLog(@"Got Device: %@",
+ IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)));
+ shortlog(kIOHIDTransportKey)
+ shortlog(kIOHIDVendorIDKey)
+ shortlog(kIOHIDVendorIDSourceKey)
+ shortlog(kIOHIDProductIDKey)
+ shortlog(kIOHIDVersionNumberKey)
+ shortlog(kIOHIDManufacturerKey)
+ shortlog(kIOHIDProductKey)
+ shortlog(kIOHIDSerialNumberKey)
+ shortlog(kIOHIDCountryCodeKey)
+ shortlog(kIOHIDLocationIDKey)
+ shortlog(kIOHIDDeviceUsageKey)
+ shortlog(kIOHIDDeviceUsagePageKey)
+ shortlog(kIOHIDDeviceUsagePairsKey)
+ shortlog(kIOHIDPrimaryUsageKey)
+ shortlog(kIOHIDPrimaryUsagePageKey)
+ shortlog(kIOHIDMaxInputReportSizeKey)
+ shortlog(kIOHIDMaxOutputReportSizeKey)
+ shortlog(kIOHIDMaxFeatureReportSizeKey)
+ shortlog(kIOHIDReportIntervalKey)
+ shortlog(kIOHIDReportDescriptorKey)
+#endif
+}
+
+static void *g_window;
+
+static void DeviceMatching_callback(void* inContext,
+ IOReturn inResult,
+ void *inSender,
+ IOHIDDeviceRef inIOHIDDeviceRef)
+{
+ NSString *pName = (NSString *)
+ IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductKey));
+ std::string name = (pName != NULL) ? [pName UTF8String] : "Unknown device";
+
+ DeviceDebugPrint(inIOHIDDeviceRef);
+
+ std::vector<Core::Device*> *devices =
+ (std::vector<Core::Device*> *)inContext;
+
+ // Add to the devices vector if it's of a type we want
+ if (IOHIDDeviceConformsTo(inIOHIDDeviceRef,
+ kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard))
+ devices->push_back(new Keyboard(inIOHIDDeviceRef,
+ name, kbd_name_counts[name]++, g_window));
+#if 0
+ else if (IOHIDDeviceConformsTo(inIOHIDDeviceRef,
+ kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse))
+ devices->push_back(new Mouse(inIOHIDDeviceRef,
+ name, mouse_name_counts[name]++));
+#endif
+ else
+ devices->push_back(new Joystick(inIOHIDDeviceRef,
+ name, joy_name_counts[name]++));
+}
+
+void Init(std::vector<Core::Device*>& devices, void *window)
+{
+ HIDManager = IOHIDManagerCreate(kCFAllocatorDefault,
+ kIOHIDOptionsTypeNone);
+ if (!HIDManager)
+ NSLog(@"Failed to create HID Manager reference");
+
+ g_window = window;
+
+ IOHIDManagerSetDeviceMatching(HIDManager, NULL);
+
+ // Callbacks for acquisition or loss of a matching device
+ IOHIDManagerRegisterDeviceMatchingCallback(HIDManager,
+ DeviceMatching_callback, (void *)&devices);
+
+ // Match devices that are plugged in right now
+ IOHIDManagerScheduleWithRunLoop(HIDManager,
+ CFRunLoopGetCurrent(), OurRunLoop);
+ if (IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone) !=
+ kIOReturnSuccess)
+ NSLog(@"Failed to open HID Manager");
+
+ kbd_name_counts.clear();
+ joy_name_counts.clear();
+
+ // Wait while current devices are initialized
+ while (CFRunLoopRunInMode(OurRunLoop, 0, TRUE) ==
+ kCFRunLoopRunHandledSource) {};
+
+ // Things should be configured now
+ // Disable hotplugging and other scheduling
+ IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, NULL, NULL);
+ IOHIDManagerUnscheduleFromRunLoop(HIDManager,
+ CFRunLoopGetCurrent(), OurRunLoop);
+}
+
+void DeInit()
+{
+ // This closes all devices as well
+ IOHIDManagerClose(HIDManager, kIOHIDOptionsTypeNone);
+ CFRelease(HIDManager);
+}
+
+
+}
+}
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h
new file mode 100644
index 0000000000..ebe908522b
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h
@@ -0,0 +1,80 @@
+#include <IOKit/hid/IOHIDLib.h>
+
+#include "../Device.h"
+
+namespace ciface
+{
+namespace OSX
+{
+
+class Joystick : public Core::Device
+{
+private:
+ class Button : public Input
+ {
+ public:
+ std::string GetName() const;
+ Button(IOHIDElementRef element, IOHIDDeviceRef device)
+ : m_element(element), m_device(device) {}
+ ControlState GetState() const;
+ private:
+ const IOHIDElementRef m_element;
+ const IOHIDDeviceRef m_device;
+ };
+
+ class Axis : public Input
+ {
+ public:
+ enum direction {
+ positive = 0,
+ negative
+ };
+ std::string GetName() const;
+ Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction dir);
+ ControlState GetState() const;
+ private:
+ const IOHIDElementRef m_element;
+ const IOHIDDeviceRef m_device;
+ std::string m_name;
+ const direction m_direction;
+ float m_neutral;
+ float m_scale;
+ };
+
+ class Hat : public Input
+ {
+ public:
+ enum direction {
+ up = 0,
+ right,
+ down,
+ left
+ };
+ std::string GetName() const;
+ Hat(IOHIDElementRef element, IOHIDDeviceRef device, direction dir);
+ ControlState GetState() const;
+ private:
+ const IOHIDElementRef m_element;
+ const IOHIDDeviceRef m_device;
+ const char* m_name;
+ const direction m_direction;
+ };
+
+public:
+ bool UpdateInput();
+ bool UpdateOutput();
+
+ Joystick(IOHIDDeviceRef device, std::string name, int index);
+
+ std::string GetName() const;
+ std::string GetSource() const;
+ int GetId() const;
+
+private:
+ const IOHIDDeviceRef m_device;
+ const std::string m_device_name;
+ const int m_index;
+};
+
+}
+}
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm
new file mode 100644
index 0000000000..ebd713d142
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm
@@ -0,0 +1,274 @@
+#include <Foundation/Foundation.h>
+#include <IOKit/hid/IOHIDLib.h>
+
+#include "OSXJoystick.h"
+
+#include <sstream>
+
+namespace ciface
+{
+namespace OSX
+{
+
+
+Joystick::Joystick(IOHIDDeviceRef device, std::string name, int index)
+ : m_device(device)
+ , m_device_name(name)
+ , m_index(index)
+{
+ // Buttons
+ NSDictionary *buttonDict =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger: kIOHIDElementTypeInput_Button],
+ @kIOHIDElementTypeKey,
+ [NSNumber numberWithInteger: kHIDPage_Button],
+ @kIOHIDElementUsagePageKey,
+ nil];
+
+ CFArrayRef buttons = IOHIDDeviceCopyMatchingElements(m_device,
+ (CFDictionaryRef)buttonDict, kIOHIDOptionsTypeNone);
+
+ if (buttons)
+ {
+ for (int i = 0; i < CFArrayGetCount(buttons); i++)
+ {
+ IOHIDElementRef e =
+ (IOHIDElementRef)CFArrayGetValueAtIndex(buttons, i);
+ //DeviceElementDebugPrint(e, NULL);
+
+ AddInput(new Button(e, m_device));
+ }
+ CFRelease(buttons);
+ }
+
+ // Axes
+ NSDictionary *axisDict =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger: kIOHIDElementTypeInput_Misc],
+ @kIOHIDElementTypeKey,
+ nil];
+
+ CFArrayRef axes = IOHIDDeviceCopyMatchingElements(m_device,
+ (CFDictionaryRef)axisDict, kIOHIDOptionsTypeNone);
+
+ if (axes)
+ {
+ for (int i = 0; i < CFArrayGetCount(axes); i++)
+ {
+ IOHIDElementRef e =
+ (IOHIDElementRef)CFArrayGetValueAtIndex(axes, i);
+ //DeviceElementDebugPrint(e, NULL);
+
+ if (IOHIDElementGetUsage(e) == kHIDUsage_GD_Hatswitch) {
+ AddInput(new Hat(e, m_device, Hat::up));
+ AddInput(new Hat(e, m_device, Hat::right));
+ AddInput(new Hat(e, m_device, Hat::down));
+ AddInput(new Hat(e, m_device, Hat::left));
+ } else {
+ AddAnalogInputs(new Axis(e, m_device, Axis::negative),
+ new Axis(e, m_device, Axis::positive));
+ }
+ }
+ CFRelease(axes);
+ }
+}
+
+bool Joystick::UpdateInput()
+{
+ return true;
+}
+
+bool Joystick::UpdateOutput()
+{
+ return true;
+}
+
+std::string Joystick::GetName() const
+{
+ return m_device_name;
+}
+
+std::string Joystick::GetSource() const
+{
+ return "Input";
+}
+
+int Joystick::GetId() const
+{
+ return m_index;
+}
+
+ControlState Joystick::Button::GetState() const
+{
+ IOHIDValueRef value;
+ if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
+ return IOHIDValueGetIntegerValue(value);
+ else
+ return 0;
+}
+
+std::string Joystick::Button::GetName() const
+{
+ std::ostringstream s;
+ s << IOHIDElementGetUsage(m_element);
+ return std::string("Button ") + s.str();
+}
+
+Joystick::Axis::Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction dir)
+ : m_element(element)
+ , m_device(device)
+ , m_direction(dir)
+{
+ // Need to parse the element a bit first
+ std::string description("unk");
+
+ int const usage = IOHIDElementGetUsage(m_element);
+ switch (usage)
+ {
+ case kHIDUsage_GD_X:
+ description = "X";
+ break;
+ case kHIDUsage_GD_Y:
+ description = "Y";
+ break;
+ case kHIDUsage_GD_Z:
+ description = "Z";
+ break;
+ case kHIDUsage_GD_Rx:
+ description = "Rx";
+ break;
+ case kHIDUsage_GD_Ry:
+ description = "Ry";
+ break;
+ case kHIDUsage_GD_Rz:
+ description = "Rz";
+ break;
+ case kHIDUsage_GD_Wheel:
+ description = "Wheel";
+ break;
+ case kHIDUsage_Csmr_ACPan:
+ description = "Pan";
+ break;
+ default:
+ {
+ std::ostringstream s;
+ s << usage;
+ description = s.str();
+ break;
+ }
+ }
+
+ m_name = std::string("Axis ") + description;
+ m_name.append((m_direction == positive) ? "+" : "-");
+
+ m_neutral = (IOHIDElementGetLogicalMax(m_element) +
+ IOHIDElementGetLogicalMin(m_element)) / 2.;
+ m_scale = 1 / fabs(IOHIDElementGetLogicalMax(m_element) - m_neutral);
+}
+
+ControlState Joystick::Axis::GetState() const
+{
+ IOHIDValueRef value;
+
+ if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
+ {
+ // IOHIDValueGetIntegerValue() crashes when trying
+ // to convert unusually large element values.
+ if (IOHIDValueGetLength(value) > 2)
+ return 0;
+
+ float position = IOHIDValueGetIntegerValue(value);
+
+ if (m_direction == positive && position > m_neutral)
+ return (position - m_neutral) * m_scale;
+ if (m_direction == negative && position < m_neutral)
+ return (m_neutral - position) * m_scale;
+ }
+
+ return 0;
+}
+
+std::string Joystick::Axis::GetName() const
+{
+ return m_name;
+}
+
+Joystick::Hat::Hat(IOHIDElementRef element, IOHIDDeviceRef device, direction dir)
+ : m_element(element)
+ , m_device(device)
+ , m_direction(dir)
+{
+ switch (dir) {
+ case up:
+ m_name = "Up";
+ break;
+ case right:
+ m_name = "Right";
+ break;
+ case down:
+ m_name = "Down";
+ break;
+ case left:
+ m_name = "Left";
+ break;
+ default:
+ m_name = "unk";
+ }
+}
+
+ControlState Joystick::Hat::GetState() const
+{
+ IOHIDValueRef value;
+ int position;
+
+ if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
+ {
+ position = IOHIDValueGetIntegerValue(value);
+
+ switch (position) {
+ case 0:
+ if (m_direction == up)
+ return 1;
+ break;
+ case 1:
+ if (m_direction == up || m_direction == right)
+ return 1;
+ break;
+ case 2:
+ if (m_direction == right)
+ return 1;
+ break;
+ case 3:
+ if (m_direction == right || m_direction == down)
+ return 1;
+ break;
+ case 4:
+ if (m_direction == down)
+ return 1;
+ break;
+ case 5:
+ if (m_direction == down || m_direction == left)
+ return 1;
+ break;
+ case 6:
+ if (m_direction == left)
+ return 1;
+ break;
+ case 7:
+ if (m_direction == left || m_direction == up)
+ return 1;
+ break;
+ };
+ }
+
+ return 0;
+}
+
+std::string Joystick::Hat::GetName() const
+{
+ return m_name;
+}
+
+
+}
+}
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h
new file mode 100644
index 0000000000..e5c2c1b3d4
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h
@@ -0,0 +1,71 @@
+#include <IOKit/hid/IOHIDLib.h>
+
+#include "../Device.h"
+
+namespace ciface
+{
+namespace OSX
+{
+
+class Keyboard : public Core::Device
+{
+private:
+ class Key : public Input
+ {
+ public:
+ std::string GetName() const;
+ Key(IOHIDElementRef element, IOHIDDeviceRef device);
+ ControlState GetState() const;
+ private:
+ const IOHIDElementRef m_element;
+ const IOHIDDeviceRef m_device;
+ std::string m_name;
+ };
+ class Cursor : public Input
+ {
+ public:
+ std::string GetName() const;
+ bool IsDetectable() { return false; }
+ Cursor(u8 index, const float& axis, const bool positive) : m_axis(axis), m_index(index), m_positive(positive) {}
+ ControlState GetState() const;
+ private:
+ const float& m_axis;
+ const u8 m_index;
+ const bool m_positive;
+ };
+ class Button : public Input
+ {
+ public:
+ std::string GetName() const;
+ Button(u8 index, const unsigned char& button) : m_button(button), m_index(index) {}
+ ControlState GetState() const;
+ private:
+ const unsigned char& m_button;
+ const u8 m_index;
+ };
+
+public:
+ bool UpdateInput();
+ bool UpdateOutput();
+
+ Keyboard(IOHIDDeviceRef device, std::string name, int index, void *window);
+
+ std::string GetName() const;
+ std::string GetSource() const;
+ int GetId() const;
+
+private:
+ struct
+ {
+ float x, y;
+ } m_cursor;
+
+ const IOHIDDeviceRef m_device;
+ const std::string m_device_name;
+ int m_index;
+ uint32_t m_windowid;
+ unsigned char m_mousebuttons[3];
+};
+
+}
+}
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.mm b/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.mm
new file mode 100644
index 0000000000..93de15daa4
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.mm
@@ -0,0 +1,276 @@
+#include <Foundation/Foundation.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <Cocoa/Cocoa.h>
+#include <wx/wx.h> // wxWidgets
+
+#include "OSXKeyboard.h"
+
+#include <sstream>
+
+namespace ciface
+{
+namespace OSX
+{
+
+Keyboard::Keyboard(IOHIDDeviceRef device, std::string name, int index, void *window)
+ : m_device(device)
+ , m_device_name(name)
+ , m_index(index)
+{
+ // This class should only recieve Keyboard or Keypad devices
+ // Now, filter on just the buttons we can handle sanely
+ NSDictionary *matchingElements =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger: kIOHIDElementTypeInput_Button],
+ @kIOHIDElementTypeKey,
+ [NSNumber numberWithInteger: 0], @kIOHIDElementMinKey,
+ [NSNumber numberWithInteger: 1], @kIOHIDElementMaxKey,
+ nil];
+
+ CFArrayRef elements = IOHIDDeviceCopyMatchingElements(m_device,
+ (CFDictionaryRef)matchingElements, kIOHIDOptionsTypeNone);
+
+ if (elements)
+ {
+ for (int i = 0; i < CFArrayGetCount(elements); i++)
+ {
+ IOHIDElementRef e =
+ (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
+ //DeviceElementDebugPrint(e, NULL);
+
+ AddInput(new Key(e, m_device));
+ }
+ CFRelease(elements);
+ }
+
+ m_windowid = [[(NSView *)(((wxWindow *)window)->GetHandle()) window] windowNumber];
+
+ // cursor, with a hax for-loop
+ for (unsigned int i=0; i<4; ++i)
+ AddInput(new Cursor(!!(i&2), (&m_cursor.x)[i/2], !!(i&1)));
+
+ for (u8 i = 0; i < sizeof(m_mousebuttons) / sizeof(m_mousebuttons[0]); ++i)
+ AddInput(new Button(i, m_mousebuttons[i]));
+}
+
+bool Keyboard::UpdateInput()
+{
+ CGRect bounds = CGRectZero;
+ uint32_t windowid[1] = { m_windowid };
+ CFArrayRef windowArray = CFArrayCreate(NULL, (const void **) windowid, 1, NULL);
+ CFArrayRef windowDescriptions = CGWindowListCreateDescriptionFromArray(windowArray);
+ CFDictionaryRef windowDescription = (CFDictionaryRef) CFArrayGetValueAtIndex((CFArrayRef) windowDescriptions, 0);
+
+ if (CFDictionaryContainsKey(windowDescription, kCGWindowBounds))
+ {
+ CFDictionaryRef boundsDictionary = (CFDictionaryRef) CFDictionaryGetValue(windowDescription, kCGWindowBounds);
+
+ if (boundsDictionary != NULL)
+ CGRectMakeWithDictionaryRepresentation(boundsDictionary, &bounds);
+ }
+
+ CFRelease(windowDescriptions);
+ CFRelease(windowArray);
+
+ CGEventRef event = CGEventCreate(nil);
+ CGPoint loc = CGEventGetLocation(event);
+ CFRelease(event);
+
+ loc.x -= bounds.origin.x;
+ loc.y -= bounds.origin.y;
+ m_cursor.x = loc.x / bounds.size.width * 2 - 1.0;
+ m_cursor.y = loc.y / bounds.size.height * 2 - 1.0;
+
+ m_mousebuttons[0] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonLeft);
+ m_mousebuttons[1] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonRight);
+ m_mousebuttons[2] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonCenter);
+
+ return true;
+}
+
+bool Keyboard::UpdateOutput()
+{
+ return true;
+}
+
+std::string Keyboard::GetName() const
+{
+ return m_device_name;
+}
+
+std::string Keyboard::GetSource() const
+{
+ return "Keyboard";
+}
+
+int Keyboard::GetId() const
+{
+ return m_index;
+}
+
+Keyboard::Key::Key(IOHIDElementRef element, IOHIDDeviceRef device)
+ : m_element(element)
+ , m_device(device)
+{
+ static const struct PrettyKeys {
+ const uint32_t code;
+ const char *const name;
+ } named_keys[] = {
+ { kHIDUsage_KeyboardA, "A" },
+ { kHIDUsage_KeyboardB, "B" },
+ { kHIDUsage_KeyboardC, "C" },
+ { kHIDUsage_KeyboardD, "D" },
+ { kHIDUsage_KeyboardE, "E" },
+ { kHIDUsage_KeyboardF, "F" },
+ { kHIDUsage_KeyboardG, "G" },
+ { kHIDUsage_KeyboardH, "H" },
+ { kHIDUsage_KeyboardI, "I" },
+ { kHIDUsage_KeyboardJ, "J" },
+ { kHIDUsage_KeyboardK, "K" },
+ { kHIDUsage_KeyboardL, "L" },
+ { kHIDUsage_KeyboardM, "M" },
+ { kHIDUsage_KeyboardN, "N" },
+ { kHIDUsage_KeyboardO, "O" },
+ { kHIDUsage_KeyboardP, "P" },
+ { kHIDUsage_KeyboardQ, "Q" },
+ { kHIDUsage_KeyboardR, "R" },
+ { kHIDUsage_KeyboardS, "S" },
+ { kHIDUsage_KeyboardT, "T" },
+ { kHIDUsage_KeyboardU, "U" },
+ { kHIDUsage_KeyboardV, "V" },
+ { kHIDUsage_KeyboardW, "W" },
+ { kHIDUsage_KeyboardX, "X" },
+ { kHIDUsage_KeyboardY, "Y" },
+ { kHIDUsage_KeyboardZ, "Z" },
+ { kHIDUsage_Keyboard1, "1" },
+ { kHIDUsage_Keyboard2, "2" },
+ { kHIDUsage_Keyboard3, "3" },
+ { kHIDUsage_Keyboard4, "4" },
+ { kHIDUsage_Keyboard5, "5" },
+ { kHIDUsage_Keyboard6, "6" },
+ { kHIDUsage_Keyboard7, "7" },
+ { kHIDUsage_Keyboard8, "8" },
+ { kHIDUsage_Keyboard9, "9" },
+ { kHIDUsage_Keyboard0, "0" },
+ { kHIDUsage_KeyboardReturnOrEnter, "Return" },
+ { kHIDUsage_KeyboardEscape, "Escape" },
+ { kHIDUsage_KeyboardDeleteOrBackspace, "Backspace" },
+ { kHIDUsage_KeyboardTab, "Tab" },
+ { kHIDUsage_KeyboardSpacebar, "Space" },
+ { kHIDUsage_KeyboardHyphen, "-" },
+ { kHIDUsage_KeyboardEqualSign, "=" },
+ { kHIDUsage_KeyboardOpenBracket, "[" },
+ { kHIDUsage_KeyboardCloseBracket, "]" },
+ { kHIDUsage_KeyboardBackslash, "\\" },
+ { kHIDUsage_KeyboardSemicolon, ";" },
+ { kHIDUsage_KeyboardQuote, "'" },
+ { kHIDUsage_KeyboardGraveAccentAndTilde, "Tilde" },
+ { kHIDUsage_KeyboardComma, "," },
+ { kHIDUsage_KeyboardPeriod, "." },
+ { kHIDUsage_KeyboardSlash, "/" },
+ { kHIDUsage_KeyboardCapsLock, "Caps Lock" },
+ { kHIDUsage_KeyboardF1, "F1" },
+ { kHIDUsage_KeyboardF2, "F2" },
+ { kHIDUsage_KeyboardF3, "F3" },
+ { kHIDUsage_KeyboardF4, "F4" },
+ { kHIDUsage_KeyboardF5, "F5" },
+ { kHIDUsage_KeyboardF6, "F6" },
+ { kHIDUsage_KeyboardF7, "F7" },
+ { kHIDUsage_KeyboardF8, "F8" },
+ { kHIDUsage_KeyboardF9, "F9" },
+ { kHIDUsage_KeyboardF10, "F10" },
+ { kHIDUsage_KeyboardF11, "F11" },
+ { kHIDUsage_KeyboardF12, "F12" },
+ { kHIDUsage_KeyboardInsert, "Insert" },
+ { kHIDUsage_KeyboardHome, "Home" },
+ { kHIDUsage_KeyboardPageUp, "Page Up" },
+ { kHIDUsage_KeyboardDeleteForward, "Delete" },
+ { kHIDUsage_KeyboardEnd, "End" },
+ { kHIDUsage_KeyboardPageDown, "Page Down" },
+ { kHIDUsage_KeyboardRightArrow, "Right Arrow" },
+ { kHIDUsage_KeyboardLeftArrow, "Left Arrow" },
+ { kHIDUsage_KeyboardDownArrow, "Down Arrow" },
+ { kHIDUsage_KeyboardUpArrow, "Up Arrow" },
+ { kHIDUsage_KeypadSlash, "Keypad /" },
+ { kHIDUsage_KeypadAsterisk, "Keypad *" },
+ { kHIDUsage_KeypadHyphen, "Keypad -" },
+ { kHIDUsage_KeypadPlus, "Keypad +" },
+ { kHIDUsage_KeypadEnter, "Keypad Enter" },
+ { kHIDUsage_Keypad1, "Keypad 1" },
+ { kHIDUsage_Keypad2, "Keypad 2" },
+ { kHIDUsage_Keypad3, "Keypad 3" },
+ { kHIDUsage_Keypad4, "Keypad 4" },
+ { kHIDUsage_Keypad5, "Keypad 5" },
+ { kHIDUsage_Keypad6, "Keypad 6" },
+ { kHIDUsage_Keypad7, "Keypad 7" },
+ { kHIDUsage_Keypad8, "Keypad 8" },
+ { kHIDUsage_Keypad9, "Keypad 9" },
+ { kHIDUsage_Keypad0, "Keypad 0" },
+ { kHIDUsage_KeypadPeriod, "Keypad ." },
+ { kHIDUsage_KeyboardNonUSBackslash, "Paragraph" },
+ { kHIDUsage_KeypadEqualSign, "Keypad =" },
+ { kHIDUsage_KeypadComma, "Keypad ," },
+ { kHIDUsage_KeyboardLeftControl, "Left Control" },
+ { kHIDUsage_KeyboardLeftShift, "Left Shift" },
+ { kHIDUsage_KeyboardLeftAlt, "Left Alt" },
+ { kHIDUsage_KeyboardLeftGUI, "Left Command" },
+ { kHIDUsage_KeyboardRightControl, "Right Control" },
+ { kHIDUsage_KeyboardRightShift, "Right Shift" },
+ { kHIDUsage_KeyboardRightAlt, "Right Alt" },
+ { kHIDUsage_KeyboardRightGUI, "Right Command" },
+ { 184, "Eject" },
+ };
+
+ const uint32_t keycode = IOHIDElementGetUsage(m_element);
+ for (auto & named_key : named_keys)
+ if (named_key.code == keycode) {
+ m_name = named_key.name;
+ return;
+ }
+
+ std::stringstream ss;
+ ss << "Key " << keycode;
+ m_name = ss.str();
+}
+
+ControlState Keyboard::Key::GetState() const
+{
+ IOHIDValueRef value;
+
+ if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
+ return IOHIDValueGetIntegerValue(value);
+ else
+ return 0;
+}
+
+ControlState Keyboard::Cursor::GetState() const
+{
+ return std::max(0.0f, ControlState(m_axis) / (m_positive ? 1.0f : -1.0f));
+}
+
+ControlState Keyboard::Button::GetState() const
+{
+ return (m_button != 0);
+}
+
+std::string Keyboard::Cursor::GetName() const
+{
+ static char tmpstr[] = "Cursor ..";
+ tmpstr[7] = (char)('X' + m_index);
+ tmpstr[8] = (m_positive ? '+' : '-');
+ return tmpstr;
+}
+
+std::string Keyboard::Button::GetName() const
+{
+ return std::string("Click ") + char('0' + m_index);
+}
+
+std::string Keyboard::Key::GetName() const
+{
+ return m_name;
+}
+
+
+}
+}