Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
macx_input.m
/* Copyright (c) Dietmar Planitzer, 1998, 2002 */ |
/* This program is freely distributable without licensing fees |
and is provided without guarantee or warrantee expressed or |
implied. This program is -not- in the public domain. */ |
#import "macx_glut.h" |
#import "GLUTView.h" |
#import <IOKit/hid/IOHIDLib.h> |
#import <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> |
static int __glutNumMouseButtons = 0; |
static BOOL __glutHaveInputDevices = NO; |
void __glutForgetInputDevices(void) |
{ |
// ensure HID stuff is torn down on app exit |
HIDReleaseDeviceList(); |
} |
/** |
* Builds the global HID list. This list contains all input devices of the |
* following classes: |
* Mouse |
* Keyboard / Keypad |
* Joystick / Gamepad |
* NOTE: This function must be called before any other HID related one. |
*/ |
void __glutCollectInputDevices(void) |
{ |
UInt32 aUsage[5]; |
UInt32 aUsagePage[5]; |
// find all |
aUsagePage[0] = 0; |
aUsage[0] = 0; |
HIDUpdateDeviceList(aUsagePage, aUsage, 1); // will do the right thing the first time |
} |
// This function will set up the input devices only the first time it is called. |
void __glutCollectInputDevicesOnce(void) |
{ |
if(!__glutHaveInputDevices) { |
__glutCollectInputDevices(); |
__glutHaveInputDevices = YES; |
} |
} |
void __glutGetInputDeviceEnumeratorOfClass(int cl, GLUTDeviceEnumerator *enumer) |
{ |
__glutCollectInputDevicesOnce(); |
enumer->typeDevice = cl; // will sort later |
enumer->curDevice = HIDGetFirstDevice(); |
enumer->done = (enumer->curDevice == NULL); |
} |
pRecDevice __glutGetNextInputDevice(GLUTDeviceEnumerator *enumer) |
{ |
pRecDevice dev = enumer->curDevice; |
UInt32 foundIt = NO; |
SInt32 usagePage[2], usage[2]; |
SInt32 numTypes = 0, i; |
if(enumer->done) |
return NULL; |
// scan device list for next device matching the required |
// usage page and usage values |
while(dev) { |
switch (enumer->typeDevice) { |
case GLUT_MOUSE_DEVICE: |
// find pointing devices |
usagePage[0] = kHIDPage_GenericDesktop; |
usage[0] = kHIDUsage_GD_Mouse; |
numTypes = 1; |
break; |
case GLUT_KEYBOARD_DEVICE: |
// find keyboards and keypads |
usagePage[0] = kHIDPage_GenericDesktop; |
usage[0] = kHIDUsage_GD_Keyboard; |
usagePage[1] = kHIDPage_GenericDesktop; |
usage[1] = kHIDUsage_GD_Keypad; |
numTypes = 2; |
break; |
case GLUT_JOYSTICK_DEVICE: // ggs: fix me, find all two axis non-relative devices |
// find joysicks and gamepads |
usagePage[0] = kHIDPage_GenericDesktop; |
usage[0] = kHIDUsage_GD_Joystick; |
usagePage[1] = kHIDPage_GenericDesktop; |
usage[1] = kHIDUsage_GD_GamePad; |
numTypes = 2; |
break; |
case GLUT_SPACEBALL_DEVICE:// ggs: fix me, find all 6 axis x, y, z, rx, ry, rz devices |
numTypes = 0; |
break; |
} |
for(i = 0; i < numTypes; i++) { |
if((usagePage[i] == dev->usagePage) && |
(usage[i] == dev->usage)) { |
foundIt = YES; |
break; |
} |
} |
// additional check for joysticks |
if ((enumer->typeDevice == GLUT_JOYSTICK_DEVICE) && // look also for 2 axis, non-mouse axis devices |
!((kHIDPage_GenericDesktop == dev->usagePage) && |
(kHIDUsage_GD_Mouse == dev->usage)) && |
(2 <= dev->axis)) |
foundIt = YES; |
// addtional check for spaceballs (note this is only thing that find spaceballs (since above numTypes is 0) |
if ((enumer->typeDevice == GLUT_SPACEBALL_DEVICE) && // look only for device with 6 axis or more |
(6 <= dev->axis)) |
foundIt = YES; |
// have we found one of the required devices ? |
if(foundIt) { |
enumer->curDevice = HIDGetNextDevice(dev); |
enumer->done = (enumer->curDevice == NULL); |
return dev; |
} |
dev = HIDGetNextDevice(dev); |
} |
// haven't found any suitable device, though checked all devices |
enumer->done = YES; |
enumer->curDevice = NULL; |
return NULL; |
} |
BOOL __glutIsInputDeviceConnected(pRecDevice device) |
{ |
pRecDevice pDevice = HIDGetFirstDevice(); // get the first device |
while(pDevice) { |
if(device == pDevice) |
return YES; |
pDevice = HIDGetNextDevice(pDevice); // check next device |
} |
return NO; |
} |
void HIDReportError (char * strError); |
void HIDReportErrorNum (char * strError, int numError); |
int GetHighestMouseButtonCount () |
{ |
int highestButtonCount; |
IOReturn result = kIOReturnSuccess; |
mach_port_t masterPort = 0; |
CFMutableDictionaryRef hiPointingDictionary = NULL; |
io_iterator_t hidObjectIterator = 0; |
io_object_t ioHIDDeviceObject = 0; |
highestButtonCount = 0; |
if (kIOReturnSuccess != IOMasterPort (bootstrap_port, &masterPort)) |
HIDReportError ("HIDCreateMultiTypeDeviceList: IOMasterPort error with bootstrap_port."); |
else |
{ |
hiPointingDictionary = IOServiceMatching ("IOHIPointing"); |
result = IOServiceGetMatchingServices (masterPort, hiPointingDictionary, &hidObjectIterator); |
if (0 != hidObjectIterator) |
{ |
while ((ioHIDDeviceObject = IOIteratorNext (hidObjectIterator))) |
{ |
int currDeviceButtonCount; |
CFTypeRef property = IORegistryEntryCreateCFProperty (ioHIDDeviceObject, CFSTR(kIOHIDPointerButtonCountKey), kCFAllocatorDefault, kNilOptions); |
if (NULL != property) |
{ |
CFNumberGetValue(property, kCFNumberIntType, &currDeviceButtonCount); |
CFRelease(property); |
if (currDeviceButtonCount > highestButtonCount) |
highestButtonCount = currDeviceButtonCount; |
} |
// dump device object, it is no longer needed |
result = IOObjectRelease (ioHIDDeviceObject); |
if (KERN_SUCCESS != result) |
HIDReportErrorNum ("IOObjectRelease error with ioHIDDeviceObject.", result); |
} |
result = IOObjectRelease (hidObjectIterator); // release the iterator |
if (kIOReturnSuccess != result) |
HIDReportErrorNum ("IOObjectRelease error with hidObjectIterator.", result); |
} |
} |
return highestButtonCount; |
} |
int __glutGetNumberOfMouseButtons(void) |
{ |
__glutNumMouseButtons = GetHighestMouseButtonCount(); |
if(__glutNumMouseButtons == 0) { |
// some pointer devices i.e. some touchpads shipped with laptops don't |
// have a button count property and can return 0 so return 1 in that case |
__glutNumMouseButtons = 1; |
} |
return __glutNumMouseButtons; |
} |
/* CENTRY */ |
int APIENTRY glutDeviceGet(GLenum param) |
{ |
int ival = 0; |
GLUTAPI_DECLARATIONS |
GLUTAPI_BEGIN |
switch(param) { |
case GLUT_HAS_KEYBOARD: |
case GLUT_HAS_MOUSE: |
ival = 1; |
break; |
case GLUT_HAS_JOYSTICK: |
if (__glutGetJoystickNumButtons() || (__glutGetJoystickNumAxis() >= 2)) // if we have buttons or axis |
ival = 1; |
break; |
case GLUT_NUM_MOUSE_BUTTONS: |
ival = __glutGetNumberOfMouseButtons(); |
break; |
case GLUT_HAS_SPACEBALL: |
if (__glutGetSpaceballNumButtons() || (__glutGetSpaceballNumAxis() == 6)) // if we have buttons or |
ival = 1; |
break; |
case GLUT_NUM_SPACEBALL_BUTTONS: |
ival = __glutGetSpaceballNumButtons(); |
break; |
case GLUT_HAS_DIAL_AND_BUTTON_BOX: |
case GLUT_HAS_TABLET: |
case GLUT_NUM_BUTTON_BOX_BUTTONS: |
case GLUT_NUM_DIALS: |
case GLUT_NUM_TABLET_BUTTONS: |
ival = 0; |
break; |
case GLUT_JOYSTICK_BUTTONS: |
ival = __glutGetJoystickNumButtons (); |
break; |
case GLUT_JOYSTICK_AXES: |
ival = __glutGetJoystickNumAxis (); |
break; |
case GLUT_DEVICE_IGNORE_KEY_REPEAT: |
ival = [__glutCurrentView ignoreKeyRepeats]; |
break; |
case GLUT_DEVICE_KEY_REPEAT: |
ival = __glutGetDeviceKeyRepeat(); |
break; |
case GLUT_JOYSTICK_POLL_RATE: |
ival = (int)([__glutCurrentView joystickPollInterval] * 1000.0); |
break; |
default: |
__glutWarning("invalid glutDeviceGet parameter: %d", param); |
ival = -1; |
break; |
} |
GLUTAPI_END |
return ival; |
} |
/* ENDCENTRY */ |
Copyright © 2008 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2008-02-08