mirror of
https://github.com/glfw/glfw.git
synced 2024-11-26 06:14:35 +00:00
Move internals to shared joystick objects
Preparation for gamecontrollerdb support and the gamepad API.
This commit is contained in:
parent
43c1910453
commit
bfd564f257
@ -32,25 +32,18 @@
|
|||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
#include <IOKit/hid/IOHIDKeys.h>
|
#include <IOKit/hid/IOHIDKeys.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
|
||||||
_GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1]
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||||
|
|
||||||
|
|
||||||
// Cocoa-specific per-joystick data
|
// Cocoa-specific per-joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickNS
|
typedef struct _GLFWjoystickNS
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
IOHIDDeviceRef device;
|
||||||
char name[256];
|
CFMutableArrayRef axes;
|
||||||
|
CFMutableArrayRef buttons;
|
||||||
IOHIDDeviceRef deviceRef;
|
CFMutableArrayRef hats;
|
||||||
|
|
||||||
CFMutableArrayRef axisElements;
|
|
||||||
CFMutableArrayRef buttonElements;
|
|
||||||
CFMutableArrayRef hatElements;
|
|
||||||
|
|
||||||
float* axes;
|
|
||||||
unsigned char* buttons;
|
|
||||||
} _GLFWjoystickNS;
|
} _GLFWjoystickNS;
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,44 +42,127 @@
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWjoyelementNS
|
typedef struct _GLFWjoyelementNS
|
||||||
{
|
{
|
||||||
IOHIDElementRef elementRef;
|
IOHIDElementRef native;
|
||||||
|
long minimum;
|
||||||
long min;
|
long maximum;
|
||||||
long max;
|
|
||||||
|
|
||||||
long minReport;
|
|
||||||
long maxReport;
|
|
||||||
|
|
||||||
} _GLFWjoyelementNS;
|
} _GLFWjoyelementNS;
|
||||||
|
|
||||||
|
|
||||||
static void getElementsCFArrayHandler(const void* value, void* parameter);
|
// Returns the value of the specified element of the specified joystick
|
||||||
|
|
||||||
// Adds an element to the specified joystick
|
|
||||||
//
|
//
|
||||||
static void addJoystickElement(_GLFWjoystickNS* js,
|
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||||
IOHIDElementRef elementRef)
|
|
||||||
{
|
{
|
||||||
IOHIDElementType elementType;
|
IOReturn result = kIOReturnSuccess;
|
||||||
long usagePage, usage;
|
IOHIDValueRef valueRef;
|
||||||
CFMutableArrayRef elementsArray = NULL;
|
long value = 0;
|
||||||
|
|
||||||
elementType = IOHIDElementGetType(elementRef);
|
if (js && element && js->ns.device)
|
||||||
usagePage = IOHIDElementGetUsagePage(elementRef);
|
|
||||||
usage = IOHIDElementGetUsage(elementRef);
|
|
||||||
|
|
||||||
if ((elementType != kIOHIDElementTypeInput_Axis) &&
|
|
||||||
(elementType != kIOHIDElementTypeInput_Button) &&
|
|
||||||
(elementType != kIOHIDElementTypeInput_Misc))
|
|
||||||
{
|
{
|
||||||
|
result = IOHIDDeviceGetValue(js->ns.device,
|
||||||
|
element->native,
|
||||||
|
&valueRef);
|
||||||
|
|
||||||
|
if (kIOReturnSuccess == result)
|
||||||
|
{
|
||||||
|
value = IOHIDValueGetIntegerValue(valueRef);
|
||||||
|
|
||||||
|
// Record min and max for auto calibration
|
||||||
|
if (value < element->minimum)
|
||||||
|
element->minimum = value;
|
||||||
|
if (value > element->maximum)
|
||||||
|
element->maximum = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto user scale
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes the specified joystick
|
||||||
|
//
|
||||||
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!js->present)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||||
|
free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
|
||||||
|
CFRelease(js->ns.axes);
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||||
|
free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
|
||||||
|
CFRelease(js->ns.buttons);
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||||
|
free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
|
||||||
|
CFRelease(js->ns.hats);
|
||||||
|
|
||||||
|
_glfwFreeJoystick(js);
|
||||||
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for user-initiated joystick addition
|
||||||
|
//
|
||||||
|
static void matchCallback(void* context,
|
||||||
|
IOReturn result,
|
||||||
|
void* sender,
|
||||||
|
IOHIDDeviceRef device)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
char name[256];
|
||||||
|
CFIndex i;
|
||||||
|
CFStringRef productKey;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
CFMutableArrayRef axes, buttons, hats;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].ns.device == device)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (usagePage)
|
axes = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
buttons = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
hats = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
|
||||||
|
productKey = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||||
|
if (productKey)
|
||||||
|
{
|
||||||
|
CFStringGetCString(productKey,
|
||||||
|
name,
|
||||||
|
sizeof(name),
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
|
CFArrayRef elements =
|
||||||
|
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(elements); i++)
|
||||||
|
{
|
||||||
|
IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
|
||||||
|
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const IOHIDElementType type = IOHIDElementGetType(native);
|
||||||
|
if ((type != kIOHIDElementTypeInput_Axis) &&
|
||||||
|
(type != kIOHIDElementTypeInput_Button) &&
|
||||||
|
(type != kIOHIDElementTypeInput_Misc))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFMutableArrayRef target = NULL;
|
||||||
|
|
||||||
|
switch (IOHIDElementGetUsagePage(native))
|
||||||
{
|
{
|
||||||
case kHIDPage_GenericDesktop:
|
case kHIDPage_GenericDesktop:
|
||||||
{
|
{
|
||||||
switch (usage)
|
switch (IOHIDElementGetUsage(native))
|
||||||
{
|
{
|
||||||
case kHIDUsage_GD_X:
|
case kHIDUsage_GD_X:
|
||||||
case kHIDUsage_GD_Y:
|
case kHIDUsage_GD_Y:
|
||||||
@ -90,10 +173,10 @@ static void addJoystickElement(_GLFWjoystickNS* js,
|
|||||||
case kHIDUsage_GD_Slider:
|
case kHIDUsage_GD_Slider:
|
||||||
case kHIDUsage_GD_Dial:
|
case kHIDUsage_GD_Dial:
|
||||||
case kHIDUsage_GD_Wheel:
|
case kHIDUsage_GD_Wheel:
|
||||||
elementsArray = js->axisElements;
|
target = axes;
|
||||||
break;
|
break;
|
||||||
case kHIDUsage_GD_Hatswitch:
|
case kHIDUsage_GD_Hatswitch:
|
||||||
elementsArray = js->hatElements;
|
target = hats;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,230 +184,34 @@ static void addJoystickElement(_GLFWjoystickNS* js,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kHIDPage_Button:
|
case kHIDPage_Button:
|
||||||
elementsArray = js->buttonElements;
|
target = buttons;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elementsArray)
|
if (target)
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||||
|
element->native = native;
|
||||||
CFArrayAppendValue(elementsArray, element);
|
element->minimum = IOHIDElementGetLogicalMin(native);
|
||||||
|
element->maximum = IOHIDElementGetLogicalMax(native);
|
||||||
element->elementRef = elementRef;
|
CFArrayAppendValue(target, element);
|
||||||
|
|
||||||
element->minReport = IOHIDElementGetLogicalMin(elementRef);
|
|
||||||
element->maxReport = IOHIDElementGetLogicalMax(elementRef);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds an element to the specified joystick
|
CFRelease(elements);
|
||||||
//
|
|
||||||
static void getElementsCFArrayHandler(const void* value, void* parameter)
|
|
||||||
{
|
|
||||||
if (CFGetTypeID(value) == IOHIDElementGetTypeID())
|
|
||||||
{
|
|
||||||
addJoystickElement((_GLFWjoystickNS*) parameter,
|
|
||||||
(IOHIDElementRef) value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the value of the specified element of the specified joystick
|
js = _glfwAllocJoystick(name,
|
||||||
//
|
CFArrayGetCount(axes),
|
||||||
static long getElementValue(_GLFWjoystickNS* js, _GLFWjoyelementNS* element)
|
CFArrayGetCount(buttons) + CFArrayGetCount(hats) * 4);
|
||||||
{
|
|
||||||
IOReturn result = kIOReturnSuccess;
|
|
||||||
IOHIDValueRef valueRef;
|
|
||||||
long value = 0;
|
|
||||||
|
|
||||||
if (js && element && js->deviceRef)
|
js->ns.device = device;
|
||||||
{
|
js->ns.axes = axes;
|
||||||
result = IOHIDDeviceGetValue(js->deviceRef,
|
js->ns.buttons = buttons;
|
||||||
element->elementRef,
|
js->ns.hats = hats;
|
||||||
&valueRef);
|
|
||||||
|
|
||||||
if (kIOReturnSuccess == result)
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED);
|
||||||
{
|
|
||||||
value = IOHIDValueGetIntegerValue(valueRef);
|
|
||||||
|
|
||||||
// Record min and max for auto calibration
|
|
||||||
if (value < element->minReport)
|
|
||||||
element->minReport = value;
|
|
||||||
if (value > element->maxReport)
|
|
||||||
element->maxReport = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto user scale
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes the specified joystick
|
|
||||||
//
|
|
||||||
static void removeJoystick(_GLFWjoystickNS* js)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!js->present)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
|
||||||
free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
|
|
||||||
CFArrayRemoveAllValues(js->axisElements);
|
|
||||||
CFRelease(js->axisElements);
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
|
||||||
free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
|
|
||||||
CFArrayRemoveAllValues(js->buttonElements);
|
|
||||||
CFRelease(js->buttonElements);
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
|
||||||
free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
|
|
||||||
CFArrayRemoveAllValues(js->hatElements);
|
|
||||||
CFRelease(js->hatElements);
|
|
||||||
|
|
||||||
free(js->axes);
|
|
||||||
free(js->buttons);
|
|
||||||
|
|
||||||
memset(js, 0, sizeof(_GLFWjoystickNS));
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Polls for joystick axis events and updates GLFW state
|
|
||||||
//
|
|
||||||
static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)
|
|
||||||
{
|
|
||||||
CFIndex i;
|
|
||||||
|
|
||||||
if (!js->present)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
|
||||||
{
|
|
||||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
|
||||||
CFArrayGetValueAtIndex(js->axisElements, i);
|
|
||||||
|
|
||||||
long value = getElementValue(js, axis);
|
|
||||||
long readScale = axis->maxReport - axis->minReport;
|
|
||||||
|
|
||||||
if (readScale == 0)
|
|
||||||
js->axes[i] = value;
|
|
||||||
else
|
|
||||||
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Polls for joystick button events and updates GLFW state
|
|
||||||
//
|
|
||||||
static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)
|
|
||||||
{
|
|
||||||
CFIndex i;
|
|
||||||
int buttonIndex = 0;
|
|
||||||
|
|
||||||
if (!js->present)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
|
||||||
{
|
|
||||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
|
||||||
CFArrayGetValueAtIndex(js->buttonElements, i);
|
|
||||||
|
|
||||||
if (getElementValue(js, button))
|
|
||||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
|
||||||
{
|
|
||||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
|
||||||
CFArrayGetValueAtIndex(js->hatElements, i);
|
|
||||||
|
|
||||||
// Bit fields of button presses for each direction, including nil
|
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
|
||||||
|
|
||||||
long j, value = getElementValue(js, hat);
|
|
||||||
if (value < 0 || value > 8)
|
|
||||||
value = 8;
|
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
|
||||||
{
|
|
||||||
if (directions[value] & (1 << j))
|
|
||||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback for user-initiated joystick addition
|
|
||||||
//
|
|
||||||
static void matchCallback(void* context,
|
|
||||||
IOReturn result,
|
|
||||||
void* sender,
|
|
||||||
IOHIDDeviceRef deviceRef)
|
|
||||||
{
|
|
||||||
_GLFWjoystickNS* js;
|
|
||||||
int jid;
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (_glfw.ns_js[jid].present && _glfw.ns_js[jid].deviceRef == deviceRef)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (!_glfw.ns_js[jid].present)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jid > GLFW_JOYSTICK_LAST)
|
|
||||||
return;
|
|
||||||
|
|
||||||
js = _glfw.ns_js + jid;
|
|
||||||
js->present = GLFW_TRUE;
|
|
||||||
js->deviceRef = deviceRef;
|
|
||||||
|
|
||||||
CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
|
|
||||||
CFSTR(kIOHIDProductKey));
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
CFStringGetCString(name,
|
|
||||||
js->name,
|
|
||||||
sizeof(js->name),
|
|
||||||
kCFStringEncodingUTF8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strncpy(js->name, "Unknown", sizeof(js->name));
|
|
||||||
|
|
||||||
js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
|
|
||||||
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
|
|
||||||
NULL,
|
|
||||||
kIOHIDOptionsTypeNone);
|
|
||||||
CFRange range = { 0, CFArrayGetCount(arrayRef) };
|
|
||||||
CFArrayApplyFunction(arrayRef,
|
|
||||||
range,
|
|
||||||
getElementsCFArrayHandler,
|
|
||||||
(void*) js);
|
|
||||||
|
|
||||||
CFRelease(arrayRef);
|
|
||||||
|
|
||||||
js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
|
|
||||||
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
|
||||||
CFArrayGetCount(js->hatElements) * 4, 1);
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for user-initiated joystick removal
|
// Callback for user-initiated joystick removal
|
||||||
@ -332,15 +219,15 @@ static void matchCallback(void* context,
|
|||||||
static void removeCallback(void* context,
|
static void removeCallback(void* context,
|
||||||
IOReturn result,
|
IOReturn result,
|
||||||
void* sender,
|
void* sender,
|
||||||
IOHIDDeviceRef deviceRef)
|
IOHIDDeviceRef device)
|
||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
{
|
||||||
if (_glfw.ns_js[jid].deviceRef == deviceRef)
|
if (_glfw.joysticks[jid].ns.device == device)
|
||||||
{
|
{
|
||||||
removeJoystick(_glfw.ns_js + jid);
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,10 +346,7 @@ void _glfwTerminateJoysticksNS(void)
|
|||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
|
||||||
removeJoystick(js);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(_glfw.ns.hidManager);
|
CFRelease(_glfw.ns.hidManager);
|
||||||
_glfw.ns.hidManager = NULL;
|
_glfw.ns.hidManager = NULL;
|
||||||
@ -473,39 +357,60 @@ void _glfwTerminateJoysticksNS(void)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int jid)
|
int _glfwPlatformPollJoystick(int jid, int mode)
|
||||||
{
|
{
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
|
||||||
|
if (mode == _GLFW_POLL_AXES)
|
||||||
|
{
|
||||||
|
CFIndex i;
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||||
|
{
|
||||||
|
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||||
|
CFArrayGetValueAtIndex(js->ns.axes, i);
|
||||||
|
|
||||||
|
const long value = getElementValue(js, axis);
|
||||||
|
const long delta = axis->maximum - axis->minimum;
|
||||||
|
|
||||||
|
if (delta == 0)
|
||||||
|
_glfwInputJoystickAxis(jid, i, value);
|
||||||
|
else
|
||||||
|
_glfwInputJoystickAxis(jid, i, (2.f * (value - axis->minimum) / delta) - 1.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == _GLFW_POLL_BUTTONS)
|
||||||
|
{
|
||||||
|
CFIndex i, bi = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||||
|
{
|
||||||
|
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||||
|
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||||
|
const char value = getElementValue(js, button) ? 1 : 0;
|
||||||
|
_glfwInputJoystickButton(jid, bi++, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||||
|
{
|
||||||
|
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||||
|
CFArrayGetValueAtIndex(js->ns.hats, i);
|
||||||
|
|
||||||
|
// Bit fields of button presses for each direction, including nil
|
||||||
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||||
|
|
||||||
|
long j, state = getElementValue(js, hat);
|
||||||
|
if (state < 0 || state > 8)
|
||||||
|
state = 8;
|
||||||
|
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
const char value = directions[state] & (1 << j) ? 1 : 0;
|
||||||
|
_glfwInputJoystickButton(jid, bi++, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return js->present;
|
return js->present;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
|
||||||
{
|
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
|
||||||
if (!pollJoystickAxisEvents(js))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = (int) CFArrayGetCount(js->axisElements);
|
|
||||||
return js->axes;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
|
||||||
{
|
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
|
||||||
if (!pollJoystickButtonEvents(js))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = (int) CFArrayGetCount(js->buttonElements) +
|
|
||||||
(int) CFArrayGetCount(js->hatElements) * 4;
|
|
||||||
return js->buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int jid)
|
|
||||||
{
|
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
|
||||||
if (!js->present)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return js->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
93
src/input.c
93
src/input.c
@ -30,6 +30,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
// Internal key state used for sticky keys
|
// Internal key state used for sticky keys
|
||||||
#define _GLFW_STICK 3
|
#define _GLFW_STICK 3
|
||||||
@ -123,12 +124,22 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
|||||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwInputJoystickChange(int jid, int event)
|
void _glfwInputJoystick(int jid, int event)
|
||||||
{
|
{
|
||||||
if (_glfw.callbacks.joystick)
|
if (_glfw.callbacks.joystick)
|
||||||
_glfw.callbacks.joystick(jid, event);
|
_glfw.callbacks.joystick(jid, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwInputJoystickAxis(int jid, int axis, float value)
|
||||||
|
{
|
||||||
|
_glfw.joysticks[jid].axes[axis] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputJoystickButton(int jid, int button, char value)
|
||||||
|
{
|
||||||
|
_glfw.joysticks[jid].buttons[button] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@ -141,6 +152,39 @@ GLFWbool _glfwIsPrintable(int key)
|
|||||||
key == GLFW_KEY_KP_EQUAL;
|
key == GLFW_KEY_KP_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jid > GLFW_JOYSTICK_LAST)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
js->present = GLFW_TRUE;
|
||||||
|
js->name = strdup(name);
|
||||||
|
js->axes = calloc(axisCount, sizeof(float));
|
||||||
|
js->buttons = calloc(buttonCount, 1);
|
||||||
|
js->axisCount = axisCount;
|
||||||
|
js->buttonCount = buttonCount;
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwFreeJoystick(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
free(js->name);
|
||||||
|
free(js->axes);
|
||||||
|
free(js->buttons);
|
||||||
|
memset(js, 0, sizeof(_GLFWjoystick));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
@ -554,20 +598,29 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
|||||||
|
|
||||||
GLFWAPI int glfwJoystickPresent(int jid)
|
GLFWAPI int glfwJoystickPresent(int jid)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||||
return 0;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformJoystickPresent(jid);
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
return _glfwPlatformPollJoystick(jid, _GLFW_POLL_PRESENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
||||||
{
|
{
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@ -578,12 +631,22 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickAxes(jid, count);
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_AXES))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = _glfw.joysticks[jid].axisCount;
|
||||||
|
return _glfw.joysticks[jid].axes;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
||||||
{
|
{
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@ -594,11 +657,21 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickButtons(jid, count);
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = _glfw.joysticks[jid].buttonCount;
|
||||||
|
return _glfw.joysticks[jid].buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||||
{
|
{
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
@ -607,7 +680,13 @@ GLFWAPI const char* glfwGetJoystickName(int jid)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickName(jid);
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_PRESENCE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return _glfw.joysticks[jid].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||||
|
@ -53,6 +53,10 @@
|
|||||||
#define _GLFW_INSERT_FIRST 0
|
#define _GLFW_INSERT_FIRST 0
|
||||||
#define _GLFW_INSERT_LAST 1
|
#define _GLFW_INSERT_LAST 1
|
||||||
|
|
||||||
|
#define _GLFW_POLL_PRESENCE 0
|
||||||
|
#define _GLFW_POLL_AXES 1
|
||||||
|
#define _GLFW_POLL_BUTTONS 2
|
||||||
|
|
||||||
typedef int GLFWbool;
|
typedef int GLFWbool;
|
||||||
|
|
||||||
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
||||||
@ -63,6 +67,7 @@ typedef struct _GLFWwindow _GLFWwindow;
|
|||||||
typedef struct _GLFWlibrary _GLFWlibrary;
|
typedef struct _GLFWlibrary _GLFWlibrary;
|
||||||
typedef struct _GLFWmonitor _GLFWmonitor;
|
typedef struct _GLFWmonitor _GLFWmonitor;
|
||||||
typedef struct _GLFWcursor _GLFWcursor;
|
typedef struct _GLFWcursor _GLFWcursor;
|
||||||
|
typedef struct _GLFWjoystick _GLFWjoystick;
|
||||||
|
|
||||||
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
||||||
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
||||||
@ -246,6 +251,9 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
y = t; \
|
y = t; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps a joystick pointer to an ID
|
||||||
|
#define _GLFW_JOYSTICK_ID(js) ((int) ((js) - _glfw.joysticks))
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Platform-independent structures
|
// Platform-independent structures
|
||||||
@ -440,6 +448,21 @@ struct _GLFWcursor
|
|||||||
_GLFW_PLATFORM_CURSOR_STATE;
|
_GLFW_PLATFORM_CURSOR_STATE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! @brief Joystick structure
|
||||||
|
*/
|
||||||
|
struct _GLFWjoystick
|
||||||
|
{
|
||||||
|
GLFWbool present;
|
||||||
|
float* axes;
|
||||||
|
int axisCount;
|
||||||
|
unsigned char* buttons;
|
||||||
|
int buttonCount;
|
||||||
|
char* name;
|
||||||
|
|
||||||
|
// This is defined in the joystick API's joystick.h
|
||||||
|
_GLFW_PLATFORM_JOYSTICK_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
/*! @brief Library global data.
|
/*! @brief Library global data.
|
||||||
*/
|
*/
|
||||||
struct _GLFWlibrary
|
struct _GLFWlibrary
|
||||||
@ -458,6 +481,8 @@ struct _GLFWlibrary
|
|||||||
_GLFWmonitor** monitors;
|
_GLFWmonitor** monitors;
|
||||||
int monitorCount;
|
int monitorCount;
|
||||||
|
|
||||||
|
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
|
||||||
uint64_t timerOffset;
|
uint64_t timerOffset;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -605,25 +630,9 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string);
|
|||||||
*/
|
*/
|
||||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
||||||
|
|
||||||
/*! @copydoc glfwJoystickPresent
|
/*! @ingroup platform
|
||||||
* @ingroup platform
|
|
||||||
*/
|
*/
|
||||||
int _glfwPlatformJoystickPresent(int jid);
|
int _glfwPlatformPollJoystick(int jid, int mode);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickAxes
|
|
||||||
* @ingroup platform
|
|
||||||
*/
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count);
|
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickButtons
|
|
||||||
* @ingroup platform
|
|
||||||
*/
|
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count);
|
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickName
|
|
||||||
* @ingroup platform
|
|
||||||
*/
|
|
||||||
const char* _glfwPlatformGetJoystickName(int jid);
|
|
||||||
|
|
||||||
/*! @copydoc glfwGetTimerValue
|
/*! @copydoc glfwGetTimerValue
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
@ -980,7 +989,21 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
|||||||
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||||
* @ingroup event
|
* @ingroup event
|
||||||
*/
|
*/
|
||||||
void _glfwInputJoystickChange(int jid, int event);
|
void _glfwInputJoystick(int jid, int event);
|
||||||
|
|
||||||
|
/*! @brief Notifies shared code of the new value of a joystick axis.
|
||||||
|
* @param[in] jid The joystick whose axis to update.
|
||||||
|
* @param[in] axis The index of the axis to update.
|
||||||
|
* @param[in] value The new value of the axis.
|
||||||
|
*/
|
||||||
|
void _glfwInputJoystickAxis(int jid, int axis, float value);
|
||||||
|
|
||||||
|
/*! @brief Notifies shared code of the new value of a joystick button.
|
||||||
|
* @param[in] jid The joystick whose button to update.
|
||||||
|
* @param[in] button The index of the button to update.
|
||||||
|
* @param[in] value The new value of the button.
|
||||||
|
*/
|
||||||
|
void _glfwInputJoystickButton(int jid, int button, char value);
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
@ -1065,6 +1088,14 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
|
|||||||
*/
|
*/
|
||||||
void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @ingroup utility
|
||||||
|
*/
|
||||||
|
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount);
|
||||||
|
|
||||||
|
/*! @ingroup utility
|
||||||
|
*/
|
||||||
|
void _glfwFreeJoystick(_GLFWjoystick* js);
|
||||||
|
|
||||||
/*! @ingroup utility
|
/*! @ingroup utility
|
||||||
*/
|
*/
|
||||||
GLFWbool _glfwIsPrintable(int key);
|
GLFWbool _glfwIsPrintable(int key);
|
||||||
|
@ -51,26 +51,16 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
char axisCount, buttonCount;
|
char axisCount, buttonCount;
|
||||||
char name[256] = "";
|
char name[256] = "";
|
||||||
int jid, fd, version;
|
int jid, fd, version;
|
||||||
_GLFWjoystickLinux* js;
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
{
|
||||||
if (!_glfw.linux_js.js[jid].present)
|
if (!_glfw.joysticks[jid].present)
|
||||||
continue;
|
continue;
|
||||||
|
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||||
if (strcmp(_glfw.linux_js.js[jid].path, path) == 0)
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (!_glfw.linux_js.js[jid].present)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jid > GLFW_JOYSTICK_LAST)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@ -87,80 +77,44 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||||
strncpy(name, "Unknown", sizeof(name));
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
js = _glfw.linux_js.js + jid;
|
|
||||||
js->present = GLFW_TRUE;
|
|
||||||
js->name = strdup(name);
|
|
||||||
js->path = strdup(path);
|
|
||||||
js->fd = fd;
|
|
||||||
|
|
||||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||||
js->axisCount = (int) axisCount;
|
|
||||||
js->axes = calloc(axisCount, sizeof(float));
|
|
||||||
|
|
||||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||||
js->buttonCount = (int) buttonCount;
|
|
||||||
js->buttons = calloc(buttonCount, 1);
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
js = _glfwAllocJoystick(name, axisCount, buttonCount);
|
||||||
|
if (!js)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
js->linjs.path = strdup(path);
|
||||||
|
js->linjs.fd = fd;
|
||||||
|
|
||||||
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED);
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
|
|
||||||
// Polls for and processes events the specified joystick
|
// Frees all resources associated with the specified joystick
|
||||||
//
|
//
|
||||||
static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
|
|
||||||
{
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwPollJoystickEvents();
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
|
|
||||||
if (!js->present)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
// Read all queued events (non-blocking)
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
struct js_event e;
|
close(js->linjs.fd);
|
||||||
|
free(js->linjs.path);
|
||||||
errno = 0;
|
_glfwFreeJoystick(js);
|
||||||
if (read(js->fd, &e, sizeof(e)) < 0)
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_DISCONNECTED);
|
||||||
{
|
|
||||||
// Reset the joystick slot if the device was disconnected
|
|
||||||
if (errno == ENODEV)
|
|
||||||
{
|
|
||||||
free(js->axes);
|
|
||||||
free(js->buttons);
|
|
||||||
free(js->name);
|
|
||||||
free(js->path);
|
|
||||||
|
|
||||||
memset(js, 0, sizeof(_GLFWjoystickLinux));
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(js - _glfw.linux_js.js,
|
|
||||||
GLFW_DISCONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the initial-state bit
|
|
||||||
e.type &= ~JS_EVENT_INIT;
|
|
||||||
|
|
||||||
if (e.type == JS_EVENT_AXIS)
|
|
||||||
js->axes[e.number] = (float) e.value / 32767.0f;
|
|
||||||
else if (e.type == JS_EVENT_BUTTON)
|
|
||||||
js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE;
|
|
||||||
}
|
}
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
return js->present;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lexically compare joysticks by name; used by qsort
|
// Lexically compare joysticks by name; used by qsort
|
||||||
//
|
//
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
static int compareJoysticks(const void* fp, const void* sp)
|
static int compareJoysticks(const void* fp, const void* sp)
|
||||||
{
|
{
|
||||||
const _GLFWjoystickLinux* fj = fp;
|
const _GLFWjoystick* fj = fp;
|
||||||
const _GLFWjoystickLinux* sj = sp;
|
const _GLFWjoystick* sj = sp;
|
||||||
return strcmp(fj->path, sj->path);
|
return strcmp(fj->linjs.path, sj->linjs.path);
|
||||||
}
|
}
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
|
|
||||||
@ -178,8 +132,8 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
const char* dirname = "/dev/input";
|
const char* dirname = "/dev/input";
|
||||||
|
|
||||||
_glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
if (_glfw.linux_js.inotify == -1)
|
if (_glfw.linjs.inotify == -1)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Linux: Failed to initialize inotify: %s",
|
"Linux: Failed to initialize inotify: %s",
|
||||||
@ -190,10 +144,10 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
// HACK: Register for IN_ATTRIB as well to get notified when udev is done
|
// HACK: Register for IN_ATTRIB as well to get notified when udev is done
|
||||||
// This works well in practice but the true way is libudev
|
// This works well in practice but the true way is libudev
|
||||||
|
|
||||||
_glfw.linux_js.watch = inotify_add_watch(_glfw.linux_js.inotify,
|
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||||
dirname,
|
dirname,
|
||||||
IN_CREATE | IN_ATTRIB);
|
IN_CREATE | IN_ATTRIB);
|
||||||
if (_glfw.linux_js.watch == -1)
|
if (_glfw.linjs.watch == -1)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Linux: Failed to watch for joystick connections in %s: %s",
|
"Linux: Failed to watch for joystick connections in %s: %s",
|
||||||
@ -202,7 +156,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
// Continue without device connection notifications
|
// Continue without device connection notifications
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regcomp(&_glfw.linux_js.regex, "^js[0-9]\\+$", 0) != 0)
|
if (regcomp(&_glfw.linjs.regex, "^js[0-9]\\+$", 0) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@ -218,7 +172,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
char path[20];
|
char path[20];
|
||||||
regmatch_t match;
|
regmatch_t match;
|
||||||
|
|
||||||
if (regexec(&_glfw.linux_js.regex, entry->d_name, 1, &match, 0) != 0)
|
if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
||||||
@ -237,7 +191,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
// Continue with no joysticks detected
|
// Continue with no joysticks detected
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(_glfw.linux_js.js, count, sizeof(_GLFWjoystickLinux), compareJoysticks);
|
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@ -248,46 +202,41 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
void _glfwTerminateJoysticksLinux(void)
|
void _glfwTerminateJoysticksLinux(void)
|
||||||
{
|
{
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int i;
|
int jid;
|
||||||
|
|
||||||
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
{
|
||||||
if (_glfw.linux_js.js[i].present)
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
{
|
if (js->present)
|
||||||
close(_glfw.linux_js.js[i].fd);
|
closeJoystick(js);
|
||||||
free(_glfw.linux_js.js[i].axes);
|
|
||||||
free(_glfw.linux_js.js[i].buttons);
|
|
||||||
free(_glfw.linux_js.js[i].name);
|
|
||||||
free(_glfw.linux_js.js[i].path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
regfree(&_glfw.linux_js.regex);
|
regfree(&_glfw.linjs.regex);
|
||||||
|
|
||||||
if (_glfw.linux_js.inotify > 0)
|
if (_glfw.linjs.inotify > 0)
|
||||||
{
|
{
|
||||||
if (_glfw.linux_js.watch > 0)
|
if (_glfw.linjs.watch > 0)
|
||||||
inotify_rm_watch(_glfw.linux_js.inotify, _glfw.linux_js.watch);
|
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
|
||||||
|
|
||||||
close(_glfw.linux_js.inotify);
|
close(_glfw.linjs.inotify);
|
||||||
}
|
}
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPollJoystickEvents(void)
|
void _glfwDetectJoystickConnectionLinux(void)
|
||||||
{
|
{
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
ssize_t offset = 0;
|
ssize_t offset = 0;
|
||||||
char buffer[16384];
|
char buffer[16384];
|
||||||
|
|
||||||
const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
|
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||||
|
|
||||||
while (size > offset)
|
while (size > offset)
|
||||||
{
|
{
|
||||||
regmatch_t match;
|
regmatch_t match;
|
||||||
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
||||||
|
|
||||||
if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
|
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) == 0)
|
||||||
{
|
{
|
||||||
char path[20];
|
char path[20];
|
||||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||||
@ -304,38 +253,35 @@ void _glfwPollJoystickEvents(void)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int jid)
|
int _glfwPlatformPollJoystick(int jid, int mode)
|
||||||
{
|
{
|
||||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
#if defined(__linux__)
|
||||||
return pollJoystickEvents(js);
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
|
||||||
|
// Read all queued events (non-blocking)
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
struct js_event e;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (read(js->linjs.fd, &e, sizeof(e)) < 0)
|
||||||
|
{
|
||||||
|
// Reset the joystick slot if the device was disconnected
|
||||||
|
if (errno == ENODEV)
|
||||||
|
closeJoystick(js);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
// Clear the initial-state bit
|
||||||
{
|
e.type &= ~JS_EVENT_INIT;
|
||||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
|
||||||
if (!pollJoystickEvents(js))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = js->axisCount;
|
if (e.type == JS_EVENT_AXIS)
|
||||||
return js->axes;
|
_glfwInputJoystickAxis(jid, e.number, e.value / 32767.0f);
|
||||||
}
|
else if (e.type == JS_EVENT_BUTTON)
|
||||||
|
_glfwInputJoystickButton(jid, e.number, e.value ? 1 : 0);
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
}
|
||||||
{
|
#endif // __linux__
|
||||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
return js->present;
|
||||||
if (!pollJoystickEvents(js))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = js->buttonCount;
|
|
||||||
return js->buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int jid)
|
|
||||||
{
|
|
||||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
|
||||||
if (!pollJoystickEvents(js))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return js->name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,40 +29,32 @@
|
|||||||
|
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoylistLinux linux_js
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
|
||||||
|
|
||||||
|
|
||||||
// Linux-specific joystick data
|
// Linux-specific joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickLinux
|
typedef struct _GLFWjoystickLinux
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
|
||||||
int fd;
|
int fd;
|
||||||
float* axes;
|
|
||||||
int axisCount;
|
|
||||||
unsigned char* buttons;
|
|
||||||
int buttonCount;
|
|
||||||
char* name;
|
|
||||||
char* path;
|
char* path;
|
||||||
} _GLFWjoystickLinux;
|
} _GLFWjoystickLinux;
|
||||||
|
|
||||||
// Linux-specific joystick API data
|
// Linux-specific joystick API data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoylistLinux
|
typedef struct _GLFWlibraryLinux
|
||||||
{
|
{
|
||||||
_GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int inotify;
|
int inotify;
|
||||||
int watch;
|
int watch;
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
#endif /*__linux__*/
|
#endif /*__linux__*/
|
||||||
} _GLFWjoylistLinux;
|
} _GLFWlibraryLinux;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitJoysticksLinux(void);
|
GLFWbool _glfwInitJoysticksLinux(void);
|
||||||
void _glfwTerminateJoysticksLinux(void);
|
void _glfwTerminateJoysticksLinux(void);
|
||||||
|
void _glfwDetectJoystickConnectionLinux(void);
|
||||||
void _glfwPollJoystickEvents(void);
|
|
||||||
|
|
||||||
#endif // _glfw3_linux_joystick_h_
|
#endif // _glfw3_linux_joystick_h_
|
||||||
|
@ -269,26 +269,11 @@ int _glfwPlatformGetKeyScancode(int key)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int joy)
|
int _glfwPlatformPollJoystick(int jid, int mode)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int joy)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,6 @@
|
|||||||
|
|
||||||
#include <initguid.h>
|
#include <initguid.h>
|
||||||
|
|
||||||
#define _GLFW_PRESENCE_ONLY 1
|
|
||||||
#define _GLFW_UPDATE_STATE 2
|
|
||||||
|
|
||||||
#define _GLFW_TYPE_AXIS 0
|
#define _GLFW_TYPE_AXIS 0
|
||||||
#define _GLFW_TYPE_SLIDER 1
|
#define _GLFW_TYPE_SLIDER 1
|
||||||
#define _GLFW_TYPE_BUTTON 2
|
#define _GLFW_TYPE_BUTTON 2
|
||||||
@ -238,21 +235,16 @@ static GLFWbool supportsXInput(const GUID* guid)
|
|||||||
|
|
||||||
// Frees all resources associated with the specified joystick
|
// Frees all resources associated with the specified joystick
|
||||||
//
|
//
|
||||||
static void closeJoystick(_GLFWjoystickWin32* js)
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
{
|
{
|
||||||
if (js->device)
|
if (js->win32.device)
|
||||||
{
|
{
|
||||||
IDirectInputDevice8_Unacquire(js->device);
|
IDirectInputDevice8_Unacquire(js->win32.device);
|
||||||
IDirectInputDevice8_Release(js->device);
|
IDirectInputDevice8_Release(js->win32.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(js->name);
|
_glfwFreeJoystick(js);
|
||||||
free(js->axes);
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_DISCONNECTED);
|
||||||
free(js->buttons);
|
|
||||||
free(js->objects);
|
|
||||||
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
|
||||||
|
|
||||||
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirectInput device object enumeration callback
|
// DirectInput device object enumeration callback
|
||||||
@ -337,23 +329,17 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
DIPROPDWORD dipd;
|
DIPROPDWORD dipd;
|
||||||
IDirectInputDevice8* device;
|
IDirectInputDevice8* device;
|
||||||
_GLFWobjenumWin32 data;
|
_GLFWobjenumWin32 data;
|
||||||
_GLFWjoystickWin32* js;
|
_GLFWjoystick* js;
|
||||||
|
char name[256];
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
{
|
||||||
if (memcmp(&_glfw.win32_js[jid].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
continue;
|
||||||
|
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (!_glfw.win32_js[jid].present)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jid > GLFW_JOYSTICK_LAST)
|
|
||||||
return DIENUM_STOP;
|
|
||||||
|
|
||||||
if (supportsXInput(&di->guidProduct))
|
if (supportsXInput(&di->guidProduct))
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
@ -426,228 +412,38 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
sizeof(_GLFWjoyobjectWin32),
|
sizeof(_GLFWjoyobjectWin32),
|
||||||
compareJoystickObjects);
|
compareJoystickObjects);
|
||||||
|
|
||||||
js = _glfw.win32_js + jid;
|
if (!WideCharToMultiByte(CP_UTF8, 0,
|
||||||
js->device = device;
|
di->tszInstanceName, -1,
|
||||||
js->guid = di->guidInstance;
|
name, sizeof(name),
|
||||||
js->axisCount = data.axisCount + data.sliderCount;
|
NULL, NULL))
|
||||||
js->axes = calloc(js->axisCount, sizeof(float));
|
{
|
||||||
js->buttonCount += data.buttonCount + data.povCount * 4;
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
js->buttons = calloc(js->buttonCount, 1);
|
"Win32: Failed to convert joystick name to UTF-8");
|
||||||
js->objects = data.objects;
|
|
||||||
js->objectCount = data.objectCount;
|
|
||||||
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
|
||||||
js->present = GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfwAllocJoystick(name,
|
||||||
|
data.axisCount + data.sliderCount,
|
||||||
|
data.buttonCount + data.povCount * 4);
|
||||||
|
if (!js)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
js->win32.device = device;
|
||||||
|
js->win32.guid = di->guidInstance;
|
||||||
|
js->win32.objects = data.objects;
|
||||||
|
js->win32.objectCount = data.objectCount;
|
||||||
|
|
||||||
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED);
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the specified joystick device
|
|
||||||
// TODO: Pack state arrays for non-gamepad devices
|
|
||||||
//
|
|
||||||
static GLFWbool openXinputDevice(DWORD index)
|
|
||||||
{
|
|
||||||
int jid;
|
|
||||||
XINPUT_CAPABILITIES xic;
|
|
||||||
_GLFWjoystickWin32* js;
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (_glfw.win32_js[jid].present &&
|
|
||||||
_glfw.win32_js[jid].device == NULL &&
|
|
||||||
_glfw.win32_js[jid].index == index)
|
|
||||||
{
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (!_glfw.win32_js[jid].present)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jid > GLFW_JOYSTICK_LAST)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
js = _glfw.win32_js + jid;
|
|
||||||
js->axisCount = 6;
|
|
||||||
js->axes = calloc(js->axisCount, sizeof(float));
|
|
||||||
js->buttonCount = 14;
|
|
||||||
js->buttons = calloc(js->buttonCount, 1);
|
|
||||||
js->present = GLFW_TRUE;
|
|
||||||
js->name = strdup(getDeviceDescription(&xic));
|
|
||||||
js->index = index;
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Polls for and processes events the specified joystick
|
|
||||||
//
|
|
||||||
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
|
|
||||||
{
|
|
||||||
if (!js->present)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (js->device)
|
|
||||||
{
|
|
||||||
int i, j, ai = 0, bi = 0;
|
|
||||||
HRESULT result;
|
|
||||||
DIJOYSTATE state;
|
|
||||||
|
|
||||||
IDirectInputDevice8_Poll(js->device);
|
|
||||||
result = IDirectInputDevice8_GetDeviceState(js->device,
|
|
||||||
sizeof(state),
|
|
||||||
&state);
|
|
||||||
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
|
||||||
{
|
|
||||||
IDirectInputDevice8_Acquire(js->device);
|
|
||||||
IDirectInputDevice8_Poll(js->device);
|
|
||||||
result = IDirectInputDevice8_GetDeviceState(js->device,
|
|
||||||
sizeof(state),
|
|
||||||
&state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
closeJoystick(js);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == _GLFW_PRESENCE_ONLY)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
for (i = 0; i < js->objectCount; i++)
|
|
||||||
{
|
|
||||||
const void* data = (char*) &state + js->objects[i].offset;
|
|
||||||
|
|
||||||
switch (js->objects[i].type)
|
|
||||||
{
|
|
||||||
case _GLFW_TYPE_AXIS:
|
|
||||||
case _GLFW_TYPE_SLIDER:
|
|
||||||
{
|
|
||||||
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case _GLFW_TYPE_BUTTON:
|
|
||||||
{
|
|
||||||
if (*((BYTE*) data) & 0x80)
|
|
||||||
js->buttons[bi++] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
js->buttons[bi++] = GLFW_RELEASE;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case _GLFW_TYPE_POV:
|
|
||||||
{
|
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
|
||||||
// Screams of horror are appropriate at this point
|
|
||||||
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
|
||||||
if (value < 0 || value > 8)
|
|
||||||
value = 8;
|
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
|
||||||
{
|
|
||||||
if (directions[value] & (1 << j))
|
|
||||||
js->buttons[bi++] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
js->buttons[bi++] = GLFW_RELEASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
DWORD result;
|
|
||||||
XINPUT_STATE xis;
|
|
||||||
const WORD buttons[14] =
|
|
||||||
{
|
|
||||||
XINPUT_GAMEPAD_A,
|
|
||||||
XINPUT_GAMEPAD_B,
|
|
||||||
XINPUT_GAMEPAD_X,
|
|
||||||
XINPUT_GAMEPAD_Y,
|
|
||||||
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
|
||||||
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
|
||||||
XINPUT_GAMEPAD_BACK,
|
|
||||||
XINPUT_GAMEPAD_START,
|
|
||||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
|
||||||
XINPUT_GAMEPAD_RIGHT_THUMB,
|
|
||||||
XINPUT_GAMEPAD_DPAD_UP,
|
|
||||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
|
||||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
|
||||||
XINPUT_GAMEPAD_DPAD_LEFT
|
|
||||||
};
|
|
||||||
|
|
||||||
result = XInputGetState(js->index, &xis);
|
|
||||||
if (result != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
|
||||||
closeJoystick(js);
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == _GLFW_PRESENCE_ONLY)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
if ((float) xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
|
||||||
(float) xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY >
|
|
||||||
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE *
|
|
||||||
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
|
||||||
{
|
|
||||||
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
|
||||||
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
js->axes[0] = 0.f;
|
|
||||||
js->axes[1] = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((float) xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
|
||||||
(float) xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY >
|
|
||||||
(float) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE *
|
|
||||||
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
|
||||||
{
|
|
||||||
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
|
||||||
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
js->axes[2] = 0.f;
|
|
||||||
js->axes[3] = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
|
||||||
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
|
||||||
else
|
|
||||||
js->axes[4] = -1.f;
|
|
||||||
|
|
||||||
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
|
||||||
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
|
||||||
else
|
|
||||||
js->axes[5] = -1.f;
|
|
||||||
|
|
||||||
for (i = 0; i < 14; i++)
|
|
||||||
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@ -679,8 +475,8 @@ void _glfwTerminateJoysticksWin32(void)
|
|||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
closeJoystick(_glfw.win32_js + jid);
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.api)
|
if (_glfw.win32.dinput8.api)
|
||||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||||
@ -692,10 +488,38 @@ void _glfwDetectJoystickConnectionWin32(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.win32.xinput.instance)
|
if (_glfw.win32.xinput.instance)
|
||||||
{
|
{
|
||||||
DWORD i;
|
DWORD index;
|
||||||
|
|
||||||
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
for (index = 0; index < XUSER_MAX_COUNT; index++)
|
||||||
openXinputDevice(i);
|
{
|
||||||
|
int jid;
|
||||||
|
XINPUT_CAPABILITIES xic;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].present &&
|
||||||
|
_glfw.joysticks[jid].win32.device == NULL &&
|
||||||
|
_glfw.joysticks[jid].win32.index == index)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jid <= GLFW_JOYSTICK_LAST)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 14);
|
||||||
|
if (!js)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
js->win32.index = index;
|
||||||
|
|
||||||
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.api)
|
if (_glfw.win32.dinput8.api)
|
||||||
@ -720,7 +544,10 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
pollJoystickState(_glfw.win32_js + jid, _GLFW_PRESENCE_ONLY);
|
{
|
||||||
|
if (_glfw.joysticks[jid].present)
|
||||||
|
_glfwPlatformPollJoystick(jid, _GLFW_POLL_PRESENCE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -728,38 +555,151 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int jid)
|
int _glfwPlatformPollJoystick(int jid, int mode)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
|
||||||
|
if (js->win32.device)
|
||||||
|
{
|
||||||
|
int i, j, ai = 0, bi = 0;
|
||||||
|
HRESULT result;
|
||||||
|
DIJOYSTATE state;
|
||||||
|
|
||||||
|
IDirectInputDevice8_Poll(js->win32.device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Acquire(js->win32.device);
|
||||||
|
IDirectInputDevice8_Poll(js->win32.device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
closeJoystick(js);
|
||||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
return GLFW_FALSE;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = js->axisCount;
|
|
||||||
return js->axes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
if (mode == _GLFW_POLL_PRESENCE)
|
||||||
{
|
return GLFW_TRUE;
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
|
||||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = js->buttonCount;
|
for (i = 0; i < js->win32.objectCount; i++)
|
||||||
return js->buttons;
|
{
|
||||||
|
const void* data = (char*) &state + js->win32.objects[i].offset;
|
||||||
|
|
||||||
|
switch (js->win32.objects[i].type)
|
||||||
|
{
|
||||||
|
case _GLFW_TYPE_AXIS:
|
||||||
|
case _GLFW_TYPE_SLIDER:
|
||||||
|
{
|
||||||
|
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||||
|
_glfwInputJoystickAxis(jid, ai, value);
|
||||||
|
ai++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int jid)
|
case _GLFW_TYPE_BUTTON:
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
const char value = (*((BYTE*) data) & 0x80) != 0;
|
||||||
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
_glfwInputJoystickButton(jid, bi, value);
|
||||||
return NULL;
|
bi++;
|
||||||
|
break;
|
||||||
return js->name;
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_POV:
|
||||||
|
{
|
||||||
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||||
|
// Screams of horror are appropriate at this point
|
||||||
|
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||||
|
if (state < 0 || state > 8)
|
||||||
|
state = 8;
|
||||||
|
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
const char value = (directions[state] & (1 << j)) != 0;
|
||||||
|
_glfwInputJoystickButton(jid, bi, value);
|
||||||
|
bi++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DWORD result;
|
||||||
|
XINPUT_STATE xis;
|
||||||
|
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
||||||
|
const WORD buttons[14] =
|
||||||
|
{
|
||||||
|
XINPUT_GAMEPAD_A,
|
||||||
|
XINPUT_GAMEPAD_B,
|
||||||
|
XINPUT_GAMEPAD_X,
|
||||||
|
XINPUT_GAMEPAD_Y,
|
||||||
|
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||||
|
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||||
|
XINPUT_GAMEPAD_BACK,
|
||||||
|
XINPUT_GAMEPAD_START,
|
||||||
|
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||||
|
XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||||
|
XINPUT_GAMEPAD_DPAD_UP,
|
||||||
|
XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||||
|
XINPUT_GAMEPAD_DPAD_DOWN,
|
||||||
|
XINPUT_GAMEPAD_DPAD_LEFT
|
||||||
|
};
|
||||||
|
|
||||||
|
result = XInputGetState(js->win32.index, &xis);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||||
|
closeJoystick(js);
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_POLL_PRESENCE)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
if ((float) xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||||
|
(float) xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY >
|
||||||
|
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE *
|
||||||
|
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
||||||
|
axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((float) xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
||||||
|
(float) xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY >
|
||||||
|
(float) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE *
|
||||||
|
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
||||||
|
axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
||||||
|
|
||||||
|
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
_glfwInputJoystickAxis(jid, i, axes[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < 14; i++)
|
||||||
|
{
|
||||||
|
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
|
_glfwInputJoystickButton(jid, i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,9 @@
|
|||||||
#ifndef _glfw3_win32_joystick_h_
|
#ifndef _glfw3_win32_joystick_h_
|
||||||
#define _glfw3_win32_joystick_h_
|
#define _glfw3_win32_joystick_h_
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
|
||||||
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
|
||||||
|
|
||||||
|
|
||||||
// Joystick element (axis, button or slider)
|
// Joystick element (axis, button or slider)
|
||||||
//
|
//
|
||||||
@ -42,14 +43,8 @@ typedef struct _GLFWjoyobjectWin32
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickWin32
|
typedef struct _GLFWjoystickWin32
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
|
||||||
float* axes;
|
|
||||||
int axisCount;
|
|
||||||
unsigned char* buttons;
|
|
||||||
int buttonCount;
|
|
||||||
_GLFWjoyobjectWin32* objects;
|
_GLFWjoyobjectWin32* objects;
|
||||||
int objectCount;
|
int objectCount;
|
||||||
char* name;
|
|
||||||
IDirectInputDevice8W* device;
|
IDirectInputDevice8W* device;
|
||||||
DWORD index;
|
DWORD index;
|
||||||
GUID guid;
|
GUID guid;
|
||||||
|
@ -62,10 +62,10 @@ static GLFWbool waitForEvent(double* timeout)
|
|||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fd, &fds);
|
FD_SET(fd, &fds);
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
FD_SET(_glfw.linux_js.inotify, &fds);
|
FD_SET(_glfw.linjs.inotify, &fds);
|
||||||
|
|
||||||
if (fd < _glfw.linux_js.inotify)
|
if (fd < _glfw.linjs.inotify)
|
||||||
count = _glfw.linux_js.inotify + 1;
|
count = _glfw.linjs.inotify + 1;
|
||||||
#endif
|
#endif
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -2153,7 +2153,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
_glfwPollJoystickEvents();
|
_glfwDetectJoystickConnectionLinux();
|
||||||
|
|
||||||
int count = XPending(_glfw.x11.display);
|
int count = XPending(_glfw.x11.display);
|
||||||
while (count--)
|
while (count--)
|
||||||
|
Loading…
Reference in New Issue
Block a user