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,61 +18,114 @@ static IOHIDManagerRef HIDManager = NULL;
static CFStringRef OurRunLoop = CFSTR("DolphinOSXInput");
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: %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)
{
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)
{
//#define shortlog(x) NSLog(@"%s: %@", x, IOHIDDeviceGetProperty(device, CFSTR(x)));
#ifdef shortlog
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
#undef shortlog
}
static void DeviceMatching_callback(void* inContext,
IOReturn inResult,
void* inSender,
IOHIDDeviceRef inIOHIDDeviceRef)
{
//NSLog(@"-------------------------");
//NSLog(@"Got Device: %@", IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductKey)));
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))
{
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext;
devices->push_back(new Keyboard(inIOHIDDeviceRef));
}
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse))
// 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)*/)
{
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext;
devices->push_back(new Mouse(inIOHIDDeviceRef));
}
/*
// 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
{
// Actually, we don't want it
#define shortlog(x)
//#define shortlog(x) NSLog(@"%s: %@", x, IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(x)));
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)
#undef shortlog
}
}
void Init( std::vector<ControllerInterface::Device*>& devices )
@ -128,60 +181,6 @@ void DeInit()
CFRelease(HIDManager);
}
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;
protected:
virtual ControlState GetState() = 0;
virtual ControlState GetState(IOHIDDeviceRef device) = 0;
};
class Key : public Input
@ -29,9 +29,8 @@ protected:
std::string GetName() const;
protected:
Key( IOHIDElementRef element );
ControlState GetState();
ControlState GetState(IOHIDDeviceRef device);
private:
IOHIDDeviceRef m_device;
IOHIDElementRef m_element;
std::string m_name;
};

View File

@ -53,6 +53,13 @@ Keyboard::Keyboard(IOHIDDeviceRef device)
try { inputs.push_back(new Key(e)); }
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);
}
@ -61,7 +68,7 @@ Keyboard::Keyboard(IOHIDDeviceRef device)
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 )
@ -98,8 +105,6 @@ Keyboard::Key::Key(IOHIDElementRef element)
: m_element(element)
, 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);
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();
}
ControlState Keyboard::Key::GetState()
ControlState Keyboard::Key::GetState(IOHIDDeviceRef device)
{
IOHIDValueRef value;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical) > 0;
if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetIntegerValue(value) > 0;
return false;
}

View File

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

View File

@ -70,7 +70,7 @@ Mouse::Mouse(IOHIDDeviceRef device)
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 )
@ -106,18 +106,16 @@ int Mouse::GetId() const
Mouse::Button::Button(IOHIDElementRef element)
: m_element(element)
{
m_device = IOHIDElementGetDevice(m_element);
std::ostringstream s;
s << IOHIDElementGetUsage(m_element);
m_name = std::string("Button ") + s.str();
}
ControlState Mouse::Button::GetState()
ControlState Mouse::Button::GetState(IOHIDDeviceRef device)
{
IOHIDValueRef value;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical) > 0;
if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetIntegerValue(value) > 0;
return false;
}
@ -132,8 +130,6 @@ Mouse::Axis::Axis(IOHIDElementRef element, direction dir)
: m_element(element)
, m_direction(dir)
{
m_device = IOHIDElementGetDevice(m_element);
// Need to parse the element a bit first
std::string description("unk");
@ -149,23 +145,33 @@ Mouse::Axis::Axis(IOHIDElementRef element, direction dir)
}
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;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
{
double scaled_value = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);
double actual_value = 0;
int int_value = IOHIDValueGetIntegerValue(value);
if ((scaled_value < 0) && (m_direction == negative))
actual_value = fabs(scaled_value);
else if ((scaled_value > 0) && (m_direction == positive))
actual_value = scaled_value;
if (((int_value < 0) && (m_direction == positive)) ||
((int_value > 0) && (m_direction == negative)) ||
!int_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;
}