osx input: scale mouse axes more nicely

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5417 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2010-04-27 15:22:23 +00:00
parent ac8bc6b350
commit ed71457d46
5 changed files with 134 additions and 126 deletions

View File

@ -18,39 +18,68 @@ static IOHIDManagerRef HIDManager = NULL;
static CFStringRef OurRunLoop = CFSTR("DolphinOSXInput"); static CFStringRef OurRunLoop = CFSTR("DolphinOSXInput");
static void DeviceMatching_callback(void* inContext, void DeviceElementDebugPrint(const void *value, void *context)
IOReturn inResult,
void* inSender,
IOHIDDeviceRef inIOHIDDeviceRef)
{ {
//NSLog(@"-------------------------"); IOHIDElementRef e = (IOHIDElementRef)value;
//NSLog(@"Got Device: %@", IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductKey))); bool recurse = false;
if (context)
recurse = *(bool*)context;
// Add to the devices vector if it's of a type we want std::string type = "";
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard) || switch (IOHIDElementGetType(e))
IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad))
{ {
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext; case kIOHIDElementTypeInput_Axis: type = "axis"; break;
devices->push_back(new Keyboard(inIOHIDDeviceRef)); 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;
} }
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse))
std::string c_type = "";
if (type == "collection")
{ {
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext; switch (IOHIDElementGetCollectionType(e))
devices->push_back(new Mouse(inIOHIDDeviceRef)); {
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;
} }
/*
// Probably just a lot of fiddling...but then we can kill SDL dependency (?)
else if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad))
{
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext;
devices->push_back();
} }
*/
else c_type.append(" ");
NSLog(@"%s%s%spage: 0x%x usage: 0x%x name: %s lmin: %i lmax: %i pmin: %i pmax: %i",
type.c_str(),
type == "collection" ? ":" : "",
type == "collection" ? c_type.c_str() : " ",
IOHIDElementGetUsagePage(e),
IOHIDElementGetUsage(e),
IOHIDElementGetName(e), // TOO BAD IT"S FUCKING USELESS
IOHIDElementGetLogicalMin(e),
IOHIDElementGetLogicalMax(e),
IOHIDElementGetPhysicalMin(e),
IOHIDElementGetPhysicalMax(e));
if ((type == "collection") && recurse)
{ {
// Actually, we don't want it CFArrayRef elements = IOHIDElementGetChildren(e);
#define shortlog(x) CFRange range = {0, CFArrayGetCount(elements)};
//#define shortlog(x) NSLog(@"%s: %@", x, IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(x))); // this leaks...but it's just debug code, right? :D
CFArrayApplyFunction(elements, range, DeviceElementDebugPrint, NULL);
}
}
void DeviceDebugPrint(IOHIDDeviceRef device)
{
//#define shortlog(x) NSLog(@"%s: %@", x, IOHIDDeviceGetProperty(device, CFSTR(x)));
#ifdef shortlog
NSLog(@"-------------------------");
NSLog(@"Got Device: %@", IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)));
shortlog(kIOHIDTransportKey) shortlog(kIOHIDTransportKey)
shortlog(kIOHIDVendorIDKey) shortlog(kIOHIDVendorIDKey)
shortlog(kIOHIDVendorIDSourceKey) shortlog(kIOHIDVendorIDSourceKey)
@ -71,8 +100,32 @@ static void DeviceMatching_callback(void* inContext,
shortlog(kIOHIDMaxFeatureReportSizeKey) shortlog(kIOHIDMaxFeatureReportSizeKey)
shortlog(kIOHIDReportIntervalKey) shortlog(kIOHIDReportIntervalKey)
shortlog(kIOHIDReportDescriptorKey) shortlog(kIOHIDReportDescriptorKey)
#endif
#undef shortlog #undef shortlog
} }
static void DeviceMatching_callback(void* inContext,
IOReturn inResult,
void* inSender,
IOHIDDeviceRef inIOHIDDeviceRef)
{
DeviceDebugPrint(inIOHIDDeviceRef);
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext;
// Add to the devices vector if it's of a type we want
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard) ||
IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad))
{
devices->push_back(new Keyboard(inIOHIDDeviceRef));
}
// We can probably generalize this class for mouse and gamepad inputs
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse) /*||
IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad)*/)
{
devices->push_back(new Mouse(inIOHIDDeviceRef));
}
} }
void Init( std::vector<ControllerInterface::Device*>& devices ) void Init( std::vector<ControllerInterface::Device*>& devices )
@ -129,60 +182,6 @@ void DeInit()
} }
void DeviceElementDebugPrint(const void *value, void *context)
{
IOHIDElementRef e = (IOHIDElementRef)value;
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: %s lmin: %i lmax: %i pmin: %i pmax: %i",
type.c_str(),
type == "collection" ? ":" : "",
type == "collection" ? c_type.c_str() : " ",
IOHIDElementGetUsagePage(e),
IOHIDElementGetUsage(e),
IOHIDElementGetName(e), // TOO BAD IT"S FUCKING USELESS
IOHIDElementGetLogicalMin(e),
IOHIDElementGetLogicalMax(e),
IOHIDElementGetPhysicalMin(e),
IOHIDElementGetPhysicalMax(e));
if (type == "collection")
{
CFArrayRef elements = IOHIDElementGetChildren(e);
CFRange range = {0, CFArrayGetCount(elements)};
// this leaks...but it's just debug code, right? :D
CFArrayApplyFunction(elements, range, DeviceElementDebugPrint, NULL);
}
}
} }
} }

View File

@ -19,7 +19,7 @@ protected:
{ {
friend class Keyboard; friend class Keyboard;
protected: protected:
virtual ControlState GetState() = 0; virtual ControlState GetState(IOHIDDeviceRef device) = 0;
}; };
class Key : public Input class Key : public Input
@ -29,9 +29,8 @@ protected:
std::string GetName() const; std::string GetName() const;
protected: protected:
Key( IOHIDElementRef element ); Key( IOHIDElementRef element );
ControlState GetState(); ControlState GetState(IOHIDDeviceRef device);
private: private:
IOHIDDeviceRef m_device;
IOHIDElementRef m_element; IOHIDElementRef m_element;
std::string m_name; std::string m_name;
}; };

View File

@ -53,6 +53,13 @@ Keyboard::Keyboard(IOHIDDeviceRef device)
try { inputs.push_back(new Key(e)); } try { inputs.push_back(new Key(e)); }
catch (std::bad_alloc&) { /*Thrown if the key is reserved*/ } catch (std::bad_alloc&) { /*Thrown if the key is reserved*/ }
} }
////
NSDictionary *melements;
kern_return_t err = kIOReturnSuccess;
if ((err = IOHIDDeviceCopyValueMultiple(m_device, elements, (CFDictionaryRef *)&melements)) != kIOReturnSuccess)
NSLog(@"FAILBOAT %x", err);
////
CFRelease(elements); CFRelease(elements);
} }
@ -61,7 +68,7 @@ Keyboard::Keyboard(IOHIDDeviceRef device)
ControlState Keyboard::GetInputState( const ControllerInterface::Device::Input* const input ) ControlState Keyboard::GetInputState( const ControllerInterface::Device::Input* const input )
{ {
return ((Input*)input)->GetState(); return ((Input*)input)->GetState(m_device);
} }
void Keyboard::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state ) void Keyboard::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
@ -98,8 +105,6 @@ Keyboard::Key::Key(IOHIDElementRef element)
: m_element(element) : m_element(element)
, m_name("RESERVED") // for some reason HID Manager gives these to us. bad_alloc! , m_name("RESERVED") // for some reason HID Manager gives these to us. bad_alloc!
{ {
m_device = IOHIDElementGetDevice(m_element);
uint32_t keycode = IOHIDElementGetUsage(m_element); uint32_t keycode = IOHIDElementGetUsage(m_element);
for (uint32_t i = 0; i < sizeof(named_keys)/sizeof(*named_keys); i++) for (uint32_t i = 0; i < sizeof(named_keys)/sizeof(*named_keys); i++)
{ {
@ -112,11 +117,11 @@ Keyboard::Key::Key(IOHIDElementRef element)
throw std::bad_alloc(); throw std::bad_alloc();
} }
ControlState Keyboard::Key::GetState() ControlState Keyboard::Key::GetState(IOHIDDeviceRef device)
{ {
IOHIDValueRef value; IOHIDValueRef value;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess) if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical) > 0; return IOHIDValueGetIntegerValue(value) > 0;
return false; return false;
} }

View File

@ -19,7 +19,7 @@ protected:
{ {
friend class Mouse; friend class Mouse;
protected: protected:
virtual ControlState GetState() = 0; virtual ControlState GetState(IOHIDDeviceRef device) = 0;
}; };
class Button : public Input class Button : public Input
@ -29,9 +29,8 @@ protected:
std::string GetName() const; std::string GetName() const;
protected: protected:
Button( IOHIDElementRef element ); Button( IOHIDElementRef element );
ControlState GetState(); ControlState GetState(IOHIDDeviceRef device);
private: private:
IOHIDDeviceRef m_device;
IOHIDElementRef m_element; IOHIDElementRef m_element;
std::string m_name; std::string m_name;
}; };
@ -47,12 +46,12 @@ protected:
std::string GetName() const; std::string GetName() const;
protected: protected:
Axis( IOHIDElementRef element, direction dir ); Axis( IOHIDElementRef element, direction dir );
ControlState GetState(); ControlState GetState(IOHIDDeviceRef device);
private: private:
IOHIDDeviceRef m_device;
IOHIDElementRef m_element; IOHIDElementRef m_element;
std::string m_name; std::string m_name;
direction m_direction; direction m_direction;
float m_range;
}; };
bool UpdateInput(); bool UpdateInput();

View File

@ -70,7 +70,7 @@ Mouse::Mouse(IOHIDDeviceRef device)
ControlState Mouse::GetInputState( const ControllerInterface::Device::Input* const input ) ControlState Mouse::GetInputState( const ControllerInterface::Device::Input* const input )
{ {
return ((Input*)input)->GetState(); return ((Input*)input)->GetState(m_device);
} }
void Mouse::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state ) void Mouse::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
@ -106,18 +106,16 @@ int Mouse::GetId() const
Mouse::Button::Button(IOHIDElementRef element) Mouse::Button::Button(IOHIDElementRef element)
: m_element(element) : m_element(element)
{ {
m_device = IOHIDElementGetDevice(m_element);
std::ostringstream s; std::ostringstream s;
s << IOHIDElementGetUsage(m_element); s << IOHIDElementGetUsage(m_element);
m_name = std::string("Button ") + s.str(); m_name = std::string("Button ") + s.str();
} }
ControlState Mouse::Button::GetState() ControlState Mouse::Button::GetState(IOHIDDeviceRef device)
{ {
IOHIDValueRef value; IOHIDValueRef value;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess) if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical) > 0; return IOHIDValueGetIntegerValue(value) > 0;
return false; return false;
} }
@ -132,8 +130,6 @@ Mouse::Axis::Axis(IOHIDElementRef element, direction dir)
: m_element(element) : m_element(element)
, m_direction(dir) , m_direction(dir)
{ {
m_device = IOHIDElementGetDevice(m_element);
// Need to parse the element a bit first // Need to parse the element a bit first
std::string description("unk"); std::string description("unk");
@ -149,23 +145,33 @@ Mouse::Axis::Axis(IOHIDElementRef element, direction dir)
} }
m_name = std::string("Axis ") + description; m_name = std::string("Axis ") + description;
m_name.append((m_direction == positive) ? std::string("+") : std::string("-")); m_name.append((m_direction == positive) ? "+" : "-");
// yeah, that factor is completely random :/
m_range = (float)IOHIDElementGetLogicalMax(m_element) / 1000.;
} }
ControlState Mouse::Axis::GetState() ControlState Mouse::Axis::GetState(IOHIDDeviceRef device)
{ {
IOHIDValueRef value; IOHIDValueRef value;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess) if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
{ {
double scaled_value = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical); int int_value = IOHIDValueGetIntegerValue(value);
double actual_value = 0;
if ((scaled_value < 0) && (m_direction == negative)) if (((int_value < 0) && (m_direction == positive)) ||
actual_value = fabs(scaled_value); ((int_value > 0) && (m_direction == negative)) ||
else if ((scaled_value > 0) && (m_direction == positive)) !int_value)
actual_value = scaled_value; return false;
float actual_value = 0;
if (int_value < 0)
actual_value = abs(int_value) / m_range;
else if (int_value > 0)
actual_value = int_value / m_range;
//NSLog(@"%s %i %f", m_name.c_str(), int_value, actual_value);
//NSLog(@"%s %f %f", m_name.c_str(), scaled_value, actual_value);
return actual_value; return actual_value;
} }