mirror of
https://github.com/glfw/glfw.git
synced 2024-11-22 21:14:35 +00:00
parent
3aebb0bfe3
commit
7cbdae1bed
@ -101,6 +101,7 @@ does not find Doxygen, the documentation will not be generated.
|
|||||||
- Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1` and `_GLFW_USE_GLESV2`
|
- Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1` and `_GLFW_USE_GLESV2`
|
||||||
configuration macros
|
configuration macros
|
||||||
- [Win32] Added support for Windows 8.1 per-monitor DPI
|
- [Win32] Added support for Windows 8.1 per-monitor DPI
|
||||||
|
- [Win32] Replaced winmm with XInput and DirectInput for joystick input
|
||||||
- [Win32] Bugfix: Window creation would segfault if video mode setting required
|
- [Win32] Bugfix: Window creation would segfault if video mode setting required
|
||||||
the system to be restarted
|
the system to be restarted
|
||||||
- [Win32] Bugfix: MinGW import library lacked the `lib` prefix
|
- [Win32] Bugfix: MinGW import library lacked the `lib` prefix
|
||||||
|
@ -86,6 +86,13 @@ static GLFWbool loadLibraries(void)
|
|||||||
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
|
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
||||||
|
|
||||||
|
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
|
||||||
|
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char* names[] =
|
const char* names[] =
|
||||||
@ -139,6 +146,9 @@ static void freeLibraries(void)
|
|||||||
if (_glfw.win32.xinput.instance)
|
if (_glfw.win32.xinput.instance)
|
||||||
FreeLibrary(_glfw.win32.xinput.instance);
|
FreeLibrary(_glfw.win32.xinput.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
FreeLibrary(_glfw.win32.dinput8.instance);
|
||||||
|
|
||||||
if (_glfw.win32.winmm.instance)
|
if (_glfw.win32.winmm.instance)
|
||||||
FreeLibrary(_glfw.win32.winmm.instance);
|
FreeLibrary(_glfw.win32.winmm.instance);
|
||||||
|
|
||||||
|
@ -29,9 +29,104 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define _GLFW_UPDATE_BUTTONS 1
|
#include <initguid.h>
|
||||||
#define _GLFW_UPDATE_AXES 2
|
|
||||||
|
|
||||||
|
#define _GLFW_PRESENCE_ONLY 1
|
||||||
|
#define _GLFW_UPDATE_STATE 2
|
||||||
|
|
||||||
|
#define _GLFW_TYPE_AXIS 0
|
||||||
|
#define _GLFW_TYPE_SLIDER 1
|
||||||
|
#define _GLFW_TYPE_BUTTON 2
|
||||||
|
#define _GLFW_TYPE_POV 3
|
||||||
|
|
||||||
|
// Data produced with DirectInput device object enumeration
|
||||||
|
//
|
||||||
|
typedef struct _GLFWobjenumWin32
|
||||||
|
{
|
||||||
|
IDirectInputDevice8W* device;
|
||||||
|
_GLFWjoyobjectWin32* objects;
|
||||||
|
int objectCount;
|
||||||
|
int axisCount;
|
||||||
|
int sliderCount;
|
||||||
|
int buttonCount;
|
||||||
|
int povCount;
|
||||||
|
} _GLFWobjenumWin32;
|
||||||
|
|
||||||
|
// Define only the necessary GUIDs (it's bad enough that we're exporting these)
|
||||||
|
//
|
||||||
|
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
|
||||||
|
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
|
||||||
|
// Object data array for our clone of c_dfDIJoystick
|
||||||
|
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
||||||
|
//
|
||||||
|
static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
|
||||||
|
{
|
||||||
|
{ &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Our clone of c_dfDIJoystick
|
||||||
|
//
|
||||||
|
static const DIDATAFORMAT _glfwDataFormat =
|
||||||
|
{
|
||||||
|
sizeof(DIDATAFORMAT),
|
||||||
|
sizeof(DIOBJECTDATAFORMAT),
|
||||||
|
DIDFT_ABSAXIS,
|
||||||
|
sizeof(DIJOYSTATE),
|
||||||
|
sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
|
||||||
|
_glfwObjectDataFormats
|
||||||
|
};
|
||||||
|
|
||||||
// Returns a description fitting the specified XInput capabilities
|
// Returns a description fitting the specified XInput capabilities
|
||||||
//
|
//
|
||||||
@ -63,10 +158,294 @@ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
|||||||
return "Unknown XInput Device";
|
return "Unknown XInput Device";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lexically compare device objects
|
||||||
|
//
|
||||||
|
static int compareJoystickObjects(const void* first, const void* second)
|
||||||
|
{
|
||||||
|
const _GLFWjoyobjectWin32* fo = first;
|
||||||
|
const _GLFWjoyobjectWin32* so = second;
|
||||||
|
|
||||||
|
if (fo->type != so->type)
|
||||||
|
return fo->type - so->type;
|
||||||
|
|
||||||
|
return fo->offset - so->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether the specified device supports XInput
|
||||||
|
// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
|
||||||
|
//
|
||||||
|
static GLFWbool supportsXInput(const GUID* guid)
|
||||||
|
{
|
||||||
|
UINT i, count;
|
||||||
|
RAWINPUTDEVICELIST* ridl;
|
||||||
|
GLFWbool result = GLFW_FALSE;
|
||||||
|
|
||||||
|
if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
|
||||||
|
|
||||||
|
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == -1)
|
||||||
|
{
|
||||||
|
free(ridl);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
RID_DEVICE_INFO rdi;
|
||||||
|
char name[256];
|
||||||
|
UINT size;
|
||||||
|
|
||||||
|
if (ridl[i].dwType != RIM_TYPEHID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ZeroMemory(&rdi, sizeof(rdi));
|
||||||
|
rdi.cbSize = sizeof(rdi);
|
||||||
|
size = sizeof(rdi);
|
||||||
|
|
||||||
|
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
||||||
|
RIDI_DEVICEINFO,
|
||||||
|
&rdi, &size) == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != guid->Data1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset(name, 0, sizeof(name));
|
||||||
|
size = sizeof(name);
|
||||||
|
|
||||||
|
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
||||||
|
RIDI_DEVICENAME,
|
||||||
|
name, &size) == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
name[sizeof(name) - 1] = '\0';
|
||||||
|
if (strstr(name, "IG_"))
|
||||||
|
{
|
||||||
|
result = GLFW_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ridl);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees all resources associated with the specified joystick
|
||||||
|
//
|
||||||
|
static void closeJoystick(_GLFWjoystickWin32* js)
|
||||||
|
{
|
||||||
|
if (js->device)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Unacquire(js->device);
|
||||||
|
IDirectInputDevice8_Release(js->device);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(js->name);
|
||||||
|
free(js->axes);
|
||||||
|
free(js->buttons);
|
||||||
|
free(js->objects);
|
||||||
|
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
||||||
|
|
||||||
|
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DirectInput device object enumeration callback
|
||||||
|
// Insights gleaned from SDL2
|
||||||
|
//
|
||||||
|
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||||
|
void* user)
|
||||||
|
{
|
||||||
|
_GLFWobjenumWin32* data = user;
|
||||||
|
_GLFWjoyobjectWin32* object = data->objects + data->objectCount;
|
||||||
|
|
||||||
|
if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
|
||||||
|
{
|
||||||
|
DIPROPRANGE dipr;
|
||||||
|
|
||||||
|
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_SLIDER(data->sliderCount);
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_X;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_Y;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_Z;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_RX;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_RY;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_RZ;
|
||||||
|
else
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
|
ZeroMemory(&dipr, sizeof(dipr));
|
||||||
|
dipr.diph.dwSize = sizeof(dipr);
|
||||||
|
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
|
||||||
|
dipr.diph.dwObj = doi->dwType;
|
||||||
|
dipr.diph.dwHow = DIPH_BYID;
|
||||||
|
dipr.lMin = -32768;
|
||||||
|
dipr.lMax = 32767;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetProperty(data->device,
|
||||||
|
DIPROP_RANGE,
|
||||||
|
&dipr.diph)))
|
||||||
|
{
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
||||||
|
{
|
||||||
|
object->type = _GLFW_TYPE_SLIDER;
|
||||||
|
data->sliderCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object->type = _GLFW_TYPE_AXIS;
|
||||||
|
data->axisCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
|
||||||
|
{
|
||||||
|
object->offset = DIJOFS_BUTTON(data->buttonCount);
|
||||||
|
object->type = _GLFW_TYPE_BUTTON;
|
||||||
|
data->buttonCount++;
|
||||||
|
}
|
||||||
|
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
|
||||||
|
{
|
||||||
|
object->offset = DIJOFS_POV(data->povCount);
|
||||||
|
object->type = _GLFW_TYPE_POV;
|
||||||
|
data->povCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->objectCount++;
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DirectInput device enumeration callback
|
||||||
|
//
|
||||||
|
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||||
|
{
|
||||||
|
int joy = 0;
|
||||||
|
DIDEVCAPS dc;
|
||||||
|
DIPROPDWORD dipd;
|
||||||
|
IDirectInputDevice8* device;
|
||||||
|
_GLFWobjenumWin32 data;
|
||||||
|
_GLFWjoystickWin32* js;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (!_glfw.win32_js[joy].present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joy > GLFW_JOYSTICK_LAST)
|
||||||
|
return DIENUM_STOP;
|
||||||
|
|
||||||
|
if (supportsXInput(&di->guidProduct))
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
|
||||||
|
&di->guidInstance,
|
||||||
|
&device,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to set device data format");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&dc, sizeof(dc));
|
||||||
|
dc.dwSize = sizeof(dc);
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to query device capabilities");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&dipd, sizeof(dipd));
|
||||||
|
dipd.diph.dwSize = sizeof(dipd);
|
||||||
|
dipd.diph.dwHeaderSize = sizeof(dipd.diph);
|
||||||
|
dipd.diph.dwHow = DIPH_DEVICE;
|
||||||
|
dipd.dwData = DIPROPAXISMODE_ABS;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetProperty(device,
|
||||||
|
DIPROP_AXISMODE,
|
||||||
|
&dipd.diph)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to set device axis mode");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.device = device;
|
||||||
|
data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs,
|
||||||
|
sizeof(_GLFWjoyobjectWin32));
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_EnumObjects(device,
|
||||||
|
deviceObjectCallback,
|
||||||
|
&data,
|
||||||
|
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to enumerate device objects");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(data.objects, data.objectCount,
|
||||||
|
sizeof(_GLFWjoyobjectWin32),
|
||||||
|
compareJoystickObjects);
|
||||||
|
|
||||||
|
js = _glfw.win32_js + joy;
|
||||||
|
js->device = device;
|
||||||
|
js->guid = di->guidInstance;
|
||||||
|
js->axisCount = data.axisCount + data.sliderCount;
|
||||||
|
js->axes = calloc(js->axisCount, sizeof(float));
|
||||||
|
js->buttonCount += data.buttonCount + data.povCount * 4;
|
||||||
|
js->buttons = calloc(js->buttonCount, 1);
|
||||||
|
js->objects = data.objects;
|
||||||
|
js->objectCount = data.objectCount;
|
||||||
|
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
||||||
|
js->present = GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to open the specified joystick device
|
// Attempt to open the specified joystick device
|
||||||
// TODO: Pack state arrays for non-gamepad devices
|
// TODO: Pack state arrays for non-gamepad devices
|
||||||
//
|
//
|
||||||
static GLFWbool openJoystickDevice(DWORD index)
|
static GLFWbool openXinputDevice(DWORD index)
|
||||||
{
|
{
|
||||||
int joy;
|
int joy;
|
||||||
XINPUT_CAPABILITIES xic;
|
XINPUT_CAPABILITIES xic;
|
||||||
@ -74,9 +453,13 @@ static GLFWbool openJoystickDevice(DWORD index)
|
|||||||
|
|
||||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
{
|
{
|
||||||
if (_glfw.win32_js[joy].present && _glfw.win32_js[joy].index == index)
|
if (_glfw.win32_js[joy].present &&
|
||||||
|
_glfw.win32_js[joy].device == NULL &&
|
||||||
|
_glfw.win32_js[joy].index == index)
|
||||||
|
{
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
{
|
{
|
||||||
@ -92,7 +475,9 @@ static GLFWbool openJoystickDevice(DWORD index)
|
|||||||
|
|
||||||
js = _glfw.win32_js + joy;
|
js = _glfw.win32_js + joy;
|
||||||
js->axisCount = 6;
|
js->axisCount = 6;
|
||||||
|
js->axes = calloc(js->axisCount, sizeof(float));
|
||||||
js->buttonCount = 14;
|
js->buttonCount = 14;
|
||||||
|
js->buttons = calloc(js->buttonCount, 1);
|
||||||
js->present = GLFW_TRUE;
|
js->present = GLFW_TRUE;
|
||||||
js->name = strdup(getDeviceDescription(&xic));
|
js->name = strdup(getDeviceDescription(&xic));
|
||||||
js->index = index;
|
js->index = index;
|
||||||
@ -104,32 +489,120 @@ static GLFWbool openJoystickDevice(DWORD index)
|
|||||||
|
|
||||||
// Polls for and processes events the specified joystick
|
// Polls for and processes events the specified joystick
|
||||||
//
|
//
|
||||||
static GLFWbool pollJoystickEvents(_GLFWjoystickWin32* js, int flags)
|
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
|
||||||
{
|
{
|
||||||
XINPUT_STATE xis;
|
|
||||||
DWORD result;
|
|
||||||
|
|
||||||
if (!_glfw.win32.xinput.instance)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!js->present)
|
if (!js->present)
|
||||||
return GLFW_FALSE;
|
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 = _glfw_XInputGetState(js->index, &xis);
|
result = _glfw_XInputGetState(js->index, &xis);
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||||
{
|
closeJoystick(js);
|
||||||
free(js->name);
|
|
||||||
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
|
||||||
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & _GLFW_UPDATE_AXES)
|
if (mode == _GLFW_PRESENCE_ONLY)
|
||||||
{
|
return GLFW_TRUE;
|
||||||
|
|
||||||
if (sqrtf((float) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
if (sqrtf((float) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||||
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
|
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
|
||||||
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
@ -165,34 +638,12 @@ static GLFWbool pollJoystickEvents(_GLFWjoystickWin32* js, int flags)
|
|||||||
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||||
else
|
else
|
||||||
js->axes[5] = -1.f;
|
js->axes[5] = -1.f;
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & _GLFW_UPDATE_BUTTONS)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; i < 14; i++)
|
for (i = 0; i < 14; i++)
|
||||||
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -204,6 +655,19 @@ static GLFWbool pollJoystickEvents(_GLFWjoystickWin32* js, int flags)
|
|||||||
//
|
//
|
||||||
void _glfwInitJoysticksWin32(void)
|
void _glfwInitJoysticksWin32(void)
|
||||||
{
|
{
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
{
|
||||||
|
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
|
||||||
|
DIRECTINPUT_VERSION,
|
||||||
|
&IID_IDirectInput8W,
|
||||||
|
(void**) &_glfw.win32.dinput8.api,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to create interface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_glfwDetectJoystickConnectionWin32();
|
_glfwDetectJoystickConnectionWin32();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,33 +678,47 @@ void _glfwTerminateJoysticksWin32(void)
|
|||||||
int joy;
|
int joy;
|
||||||
|
|
||||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
free(_glfw.win32_js[joy].name);
|
closeJoystick(_glfw.win32_js + joy);
|
||||||
|
|
||||||
|
if (_glfw.win32.dinput8.api)
|
||||||
|
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Looks for new joysticks
|
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
||||||
//
|
//
|
||||||
void _glfwDetectJoystickConnectionWin32(void)
|
void _glfwDetectJoystickConnectionWin32(void)
|
||||||
{
|
{
|
||||||
|
if (_glfw.win32.xinput.instance)
|
||||||
|
{
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
if (!_glfw.win32.xinput.instance)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
||||||
openJoystickDevice(i);
|
openXinputDevice(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.win32.dinput8.api)
|
||||||
|
{
|
||||||
|
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
|
||||||
|
DI8DEVCLASS_GAMECTRL,
|
||||||
|
deviceCallback,
|
||||||
|
NULL,
|
||||||
|
DIEDFL_ALLDEVICES)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Failed to enumerate DirectInput8 devices");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if any current joystick has been disconnected
|
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
|
||||||
//
|
//
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void)
|
void _glfwDetectJoystickDisconnectionWin32(void)
|
||||||
{
|
{
|
||||||
DWORD i;
|
int joy;
|
||||||
|
|
||||||
if (!_glfw.win32.xinput.instance)
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
return;
|
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
|
||||||
|
|
||||||
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
|
||||||
pollJoystickEvents(_glfw.win32_js + i, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -251,13 +729,13 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||||||
int _glfwPlatformJoystickPresent(int joy)
|
int _glfwPlatformJoystickPresent(int joy)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
return pollJoystickEvents(js, 0);
|
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
if (!pollJoystickEvents(js, _GLFW_UPDATE_AXES))
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*count = js->axisCount;
|
*count = js->axisCount;
|
||||||
@ -267,7 +745,7 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
if (!pollJoystickEvents(js, _GLFW_UPDATE_BUTTONS))
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*count = js->buttonCount;
|
*count = js->buttonCount;
|
||||||
@ -277,7 +755,7 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
|||||||
const char* _glfwPlatformGetJoystickName(int joy)
|
const char* _glfwPlatformGetJoystickName(int joy)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
if (!pollJoystickEvents(js, 0))
|
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return js->name;
|
return js->name;
|
||||||
|
@ -30,17 +30,29 @@
|
|||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||||
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
||||||
|
|
||||||
|
// Spoo
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoyobjectWin32
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int type;
|
||||||
|
} _GLFWjoyobjectWin32;
|
||||||
|
|
||||||
// Win32-specific per-joystick data
|
// Win32-specific per-joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickWin32
|
typedef struct _GLFWjoystickWin32
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
GLFWbool present;
|
||||||
float axes[6];
|
float* axes;
|
||||||
int axisCount;
|
int axisCount;
|
||||||
unsigned char buttons[14];
|
unsigned char* buttons;
|
||||||
int buttonCount;
|
int buttonCount;
|
||||||
|
_GLFWjoyobjectWin32* objects;
|
||||||
|
int objectCount;
|
||||||
char* name;
|
char* name;
|
||||||
|
IDirectInputDevice8W* device;
|
||||||
DWORD index;
|
DWORD index;
|
||||||
|
GUID guid;
|
||||||
} _GLFWjoystickWin32;
|
} _GLFWjoystickWin32;
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,8 +61,12 @@
|
|||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// GLFW uses DirectInput8 interfaces
|
||||||
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
|
#include <dinput.h>
|
||||||
#include <xinput.h>
|
#include <xinput.h>
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
|
|
||||||
@ -71,7 +75,7 @@
|
|||||||
#define strdup _strdup
|
#define strdup _strdup
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// HACK: Define macros that some older windows.h variants don't
|
// HACK: Define macros that some windows.h variants don't
|
||||||
#ifndef WM_MOUSEHWHEEL
|
#ifndef WM_MOUSEHWHEEL
|
||||||
#define WM_MOUSEHWHEEL 0x020E
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
#endif
|
#endif
|
||||||
@ -121,7 +125,7 @@ typedef enum PROCESS_DPI_AWARENESS
|
|||||||
} PROCESS_DPI_AWARENESS;
|
} PROCESS_DPI_AWARENESS;
|
||||||
#endif /*DPI_ENUMS_DECLARED*/
|
#endif /*DPI_ENUMS_DECLARED*/
|
||||||
|
|
||||||
// HACK: Define macros that some older xinput.h variants don't
|
// HACK: Define macros that some xinput.h variants don't
|
||||||
#ifndef XINPUT_CAPS_WIRELESS
|
#ifndef XINPUT_CAPS_WIRELESS
|
||||||
#define XINPUT_CAPS_WIRELESS 0x0002
|
#define XINPUT_CAPS_WIRELESS 0x0002
|
||||||
#endif
|
#endif
|
||||||
@ -147,6 +151,11 @@ typedef enum PROCESS_DPI_AWARENESS
|
|||||||
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// HACK: Define macros that some dinput.h variants don't
|
||||||
|
#ifndef DIDFT_OPTIONAL
|
||||||
|
#define DIDFT_OPTIONAL 0x80000000
|
||||||
|
#endif
|
||||||
|
|
||||||
// winmm.dll function pointer typedefs
|
// winmm.dll function pointer typedefs
|
||||||
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
|
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
|
||||||
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
||||||
@ -157,6 +166,10 @@ typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
|
|||||||
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
||||||
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
||||||
|
|
||||||
|
// dinput8.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||||
|
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
|
||||||
|
|
||||||
// user32.dll function pointer typedefs
|
// user32.dll function pointer typedefs
|
||||||
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
|
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
|
||||||
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
||||||
@ -241,13 +254,17 @@ typedef struct _GLFWlibraryWin32
|
|||||||
short int publicKeys[512];
|
short int publicKeys[512];
|
||||||
short int nativeKeys[GLFW_KEY_LAST + 1];
|
short int nativeKeys[GLFW_KEY_LAST + 1];
|
||||||
|
|
||||||
// winmm.dll
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
TIMEGETTIME_T timeGetTime;
|
TIMEGETTIME_T timeGetTime;
|
||||||
} winmm;
|
} winmm;
|
||||||
|
|
||||||
// user32.dll
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
DIRECTINPUT8CREATE_T DirectInput8Create;
|
||||||
|
IDirectInput8W* api;
|
||||||
|
} dinput8;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
|
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
|
||||||
@ -260,14 +277,12 @@ typedef struct _GLFWlibraryWin32
|
|||||||
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
|
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
|
||||||
} user32;
|
} user32;
|
||||||
|
|
||||||
// dwmapi.dll
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
|
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
|
||||||
DWMFLUSH_T DwmFlush;
|
DWMFLUSH_T DwmFlush;
|
||||||
} dwmapi;
|
} dwmapi;
|
||||||
|
|
||||||
// shcore.dll
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
|
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
|
||||||
|
Loading…
Reference in New Issue
Block a user