mirror of
https://github.com/gwm17/glfw.git
synced 2024-11-26 20:28:49 -05:00
Add initial XInput support
This commit is contained in:
parent
9f1474c1d0
commit
eb3577c1eb
|
@ -30,6 +30,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include <initguid.h>
|
||||||
|
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
|
||||||
|
|
||||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
|
||||||
|
@ -69,12 +71,6 @@ static GLFWbool loadLibraries(void)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.win32.winmm.joyGetDevCaps = (JOYGETDEVCAPS_T)
|
|
||||||
GetProcAddress(_glfw.win32.winmm.instance, "joyGetDevCapsW");
|
|
||||||
_glfw.win32.winmm.joyGetPos = (JOYGETPOS_T)
|
|
||||||
GetProcAddress(_glfw.win32.winmm.instance, "joyGetPos");
|
|
||||||
_glfw.win32.winmm.joyGetPosEx = (JOYGETPOSEX_T)
|
|
||||||
GetProcAddress(_glfw.win32.winmm.instance, "joyGetPosEx");
|
|
||||||
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
|
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
|
||||||
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
||||||
|
|
||||||
|
@ -90,6 +86,33 @@ 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");
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* names[] =
|
||||||
|
{
|
||||||
|
"xinput1_4.dll",
|
||||||
|
"xinput1_3.dll",
|
||||||
|
"xinput9_1_0.dll",
|
||||||
|
"xinput1_2.dll",
|
||||||
|
"xinput1_1.dll",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; names[i]; i++)
|
||||||
|
{
|
||||||
|
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
||||||
|
if (_glfw.win32.xinput.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
|
||||||
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
||||||
|
_glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
|
||||||
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||||
if (_glfw.win32.dwmapi.instance)
|
if (_glfw.win32.dwmapi.instance)
|
||||||
{
|
{
|
||||||
|
@ -113,6 +136,9 @@ static GLFWbool loadLibraries(void)
|
||||||
//
|
//
|
||||||
static void freeLibraries(void)
|
static void freeLibraries(void)
|
||||||
{
|
{
|
||||||
|
if (_glfw.win32.xinput.instance)
|
||||||
|
FreeLibrary(_glfw.win32.xinput.instance);
|
||||||
|
|
||||||
if (_glfw.win32.winmm.instance)
|
if (_glfw.win32.winmm.instance)
|
||||||
FreeLibrary(_glfw.win32.winmm.instance);
|
FreeLibrary(_glfw.win32.winmm.instance);
|
||||||
|
|
||||||
|
@ -283,7 +309,20 @@ static HWND createHelperWindow(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return window;
|
// Register for HID device notifications
|
||||||
|
{
|
||||||
|
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
|
||||||
|
ZeroMemory(&dbi, sizeof(dbi));
|
||||||
|
dbi.dbcc_size = sizeof(dbi);
|
||||||
|
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||||
|
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||||
|
|
||||||
|
RegisterDeviceNotificationW(window,
|
||||||
|
(DEV_BROADCAST_HDR*) &dbi,
|
||||||
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.2 Win32 - www.glfw.org
|
// GLFW 3.1 Win32 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
// Copyright (c) 2006-2015 Camilla Berglund <elmindreda@elmindreda.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -27,22 +27,169 @@
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#define _GLFW_UPDATE_BUTTONS 1
|
||||||
|
#define _GLFW_UPDATE_AXES 2
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
// Returns a description fitting the specified XInput capabilities
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Convert axis value to the [-1,1] range
|
|
||||||
//
|
//
|
||||||
static float normalizeAxis(DWORD pos, DWORD min, DWORD max)
|
static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
||||||
{
|
{
|
||||||
float fpos = (float) pos;
|
switch (xic->SubType)
|
||||||
float fmin = (float) min;
|
{
|
||||||
float fmax = (float) max;
|
case XINPUT_DEVSUBTYPE_WHEEL:
|
||||||
|
return "XInput Wheel";
|
||||||
|
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
||||||
|
return "XInput Arcade Stick";
|
||||||
|
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
||||||
|
return "XInput Flight Stick";
|
||||||
|
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
||||||
|
return "XInput Dance Pad";
|
||||||
|
case XINPUT_DEVSUBTYPE_GUITAR:
|
||||||
|
return "XInput Guitar";
|
||||||
|
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
||||||
|
return "XInput Drum Kit";
|
||||||
|
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||||
|
{
|
||||||
|
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
||||||
|
return "Wireless Xbox 360 Controller";
|
||||||
|
else
|
||||||
|
return "Xbox 360 Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (2.f * (fpos - fmin) / (fmax - fmin)) - 1.f;
|
return "Unknown XInput Device";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to open the specified joystick device
|
||||||
|
// TODO: Pack state arrays for non-gamepad devices
|
||||||
|
//
|
||||||
|
static GLFWbool openJoystickDevice(DWORD index)
|
||||||
|
{
|
||||||
|
int joy;
|
||||||
|
XINPUT_CAPABILITIES xic;
|
||||||
|
_GLFWjoystickWin32* js;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (_glfw.win32_js[joy].present && _glfw.win32_js[joy].index == index)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (!_glfw.win32_js[joy].present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joy > GLFW_JOYSTICK_LAST)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
js = _glfw.win32_js + joy;
|
||||||
|
js->axisCount = 6;
|
||||||
|
js->buttonCount = 14;
|
||||||
|
js->present = GLFW_TRUE;
|
||||||
|
js->name = strdup(getDeviceDescription(&xic));
|
||||||
|
js->index = index;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polls for and processes events the specified joystick
|
||||||
|
//
|
||||||
|
static GLFWbool pollJoystickEvents(_GLFWjoystickWin32* js, int flags)
|
||||||
|
{
|
||||||
|
XINPUT_STATE xis;
|
||||||
|
DWORD result;
|
||||||
|
|
||||||
|
if (!_glfw.win32.xinput.instance)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!js->present)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
result = _glfw_XInputGetState(js->index, &xis);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||||
|
{
|
||||||
|
free(js->name);
|
||||||
|
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & _GLFW_UPDATE_AXES)
|
||||||
|
{
|
||||||
|
if (sqrtf((float) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||||
|
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
|
||||||
|
(float) 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 (sqrtf((float) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
||||||
|
xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
|
||||||
|
(float) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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++)
|
||||||
|
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,16 +201,43 @@ static float normalizeAxis(DWORD pos, DWORD min, DWORD max)
|
||||||
//
|
//
|
||||||
void _glfwInitJoysticksWin32(void)
|
void _glfwInitJoysticksWin32(void)
|
||||||
{
|
{
|
||||||
|
_glfwDetectJoystickConnectionWin32();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close all opened joystick handles
|
// Close all opened joystick handles
|
||||||
//
|
//
|
||||||
void _glfwTerminateJoysticksWin32(void)
|
void _glfwTerminateJoysticksWin32(void)
|
||||||
{
|
{
|
||||||
int i;
|
int joy;
|
||||||
|
|
||||||
for (i = 0; i < GLFW_JOYSTICK_LAST; i++)
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
free(_glfw.win32_js[i].name);
|
free(_glfw.win32_js[joy].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looks for new joysticks
|
||||||
|
//
|
||||||
|
void _glfwDetectJoystickConnectionWin32(void)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
if (!_glfw.win32.xinput.instance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
||||||
|
openJoystickDevice(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if any current joystick has been disconnected
|
||||||
|
//
|
||||||
|
void _glfwDetectJoystickDisconnectionWin32(void)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
if (!_glfw.win32.xinput.instance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
||||||
|
pollJoystickEvents(_glfw.win32_js + i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,105 +247,36 @@ void _glfwTerminateJoysticksWin32(void)
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int joy)
|
int _glfwPlatformJoystickPresent(int joy)
|
||||||
{
|
{
|
||||||
JOYINFO ji;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
|
return pollJoystickEvents(js, 0);
|
||||||
if (_glfw_joyGetPos(joy, &ji) != JOYERR_NOERROR)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
JOYINFOEX ji;
|
if (!pollJoystickEvents(js, _GLFW_UPDATE_AXES))
|
||||||
float* axes = _glfw.win32_js[joy].axes;
|
|
||||||
|
|
||||||
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ji.dwSize = sizeof(JOYINFOEX);
|
*count = js->axisCount;
|
||||||
ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |
|
return js->axes;
|
||||||
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;
|
|
||||||
if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
axes[(*count)++] = normalizeAxis(ji.dwXpos, jc.wXmin, jc.wXmax);
|
|
||||||
axes[(*count)++] = normalizeAxis(ji.dwYpos, jc.wYmin, jc.wYmax);
|
|
||||||
|
|
||||||
if (jc.wCaps & JOYCAPS_HASZ)
|
|
||||||
axes[(*count)++] = normalizeAxis(ji.dwZpos, jc.wZmin, jc.wZmax);
|
|
||||||
|
|
||||||
if (jc.wCaps & JOYCAPS_HASR)
|
|
||||||
axes[(*count)++] = normalizeAxis(ji.dwRpos, jc.wRmin, jc.wRmax);
|
|
||||||
|
|
||||||
if (jc.wCaps & JOYCAPS_HASU)
|
|
||||||
axes[(*count)++] = normalizeAxis(ji.dwUpos, jc.wUmin, jc.wUmax);
|
|
||||||
|
|
||||||
if (jc.wCaps & JOYCAPS_HASV)
|
|
||||||
axes[(*count)++] = normalizeAxis(ji.dwVpos, jc.wVmin, jc.wVmax);
|
|
||||||
|
|
||||||
return axes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
JOYINFOEX ji;
|
if (!pollJoystickEvents(js, _GLFW_UPDATE_BUTTONS))
|
||||||
unsigned char* buttons = _glfw.win32_js[joy].buttons;
|
|
||||||
|
|
||||||
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ji.dwSize = sizeof(JOYINFOEX);
|
*count = js->buttonCount;
|
||||||
ji.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;
|
return js->buttons;
|
||||||
if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
while (*count < (int) jc.wNumButtons)
|
|
||||||
{
|
|
||||||
buttons[*count] = (unsigned char)
|
|
||||||
(ji.dwButtons & (1UL << *count) ? GLFW_PRESS : GLFW_RELEASE);
|
|
||||||
(*count)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Virtual buttons - Inject data from hats
|
|
||||||
// Each hat is exposed as 4 buttons which exposes 8 directions with
|
|
||||||
// concurrent button presses
|
|
||||||
// NOTE: this API exposes only one hat
|
|
||||||
|
|
||||||
if ((jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR))
|
|
||||||
{
|
|
||||||
int i, value = ji.dwPOV / 100 / 45;
|
|
||||||
|
|
||||||
// Bit fields of button presses for each direction, including nil
|
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
|
||||||
|
|
||||||
if (value < 0 || value > 8)
|
|
||||||
value = 8;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
if (directions[value] & (1 << i))
|
|
||||||
buttons[(*count)++] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
buttons[(*count)++] = GLFW_RELEASE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buttons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int joy)
|
const char* _glfwPlatformGetJoystickName(int joy)
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
|
if (!pollJoystickEvents(js, 0))
|
||||||
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
free(_glfw.win32_js[joy].name);
|
return js->name;
|
||||||
_glfw.win32_js[joy].name = _glfwCreateUTF8FromWideStringWin32(jc.szPname);
|
|
||||||
|
|
||||||
return _glfw.win32_js[joy].name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,18 +30,23 @@
|
||||||
#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]
|
||||||
|
|
||||||
|
|
||||||
// Win32-specific per-joystick data
|
// Win32-specific per-joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickWin32
|
typedef struct _GLFWjoystickWin32
|
||||||
{
|
{
|
||||||
|
GLFWbool present;
|
||||||
float axes[6];
|
float axes[6];
|
||||||
unsigned char buttons[36]; // 32 buttons plus one hat
|
int axisCount;
|
||||||
|
unsigned char buttons[14];
|
||||||
|
int buttonCount;
|
||||||
char* name;
|
char* name;
|
||||||
|
DWORD index;
|
||||||
} _GLFWjoystickWin32;
|
} _GLFWjoystickWin32;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitJoysticksWin32(void);
|
void _glfwInitJoysticksWin32(void);
|
||||||
void _glfwTerminateJoysticksWin32(void);
|
void _glfwTerminateJoysticksWin32(void);
|
||||||
|
void _glfwDetectJoystickConnectionWin32(void);
|
||||||
|
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||||
|
|
||||||
#endif // _glfw3_win32_joystick_h_
|
#endif // _glfw3_win32_joystick_h_
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
|
#include <xinput.h>
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
@ -120,16 +121,42 @@ 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
|
||||||
|
#ifndef XINPUT_CAPS_WIRELESS
|
||||||
|
#define XINPUT_CAPS_WIRELESS 0x0002
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_WHEEL
|
||||||
|
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
|
||||||
|
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
|
||||||
|
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
|
||||||
|
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_GUITAR
|
||||||
|
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
|
||||||
|
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
|
||||||
|
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
||||||
|
#endif
|
||||||
|
|
||||||
// winmm.dll function pointer typedefs
|
// winmm.dll function pointer typedefs
|
||||||
typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T)(UINT,LPJOYCAPS,UINT);
|
|
||||||
typedef MMRESULT (WINAPI * JOYGETPOS_T)(UINT,LPJOYINFO);
|
|
||||||
typedef MMRESULT (WINAPI * JOYGETPOSEX_T)(UINT,LPJOYINFOEX);
|
|
||||||
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
|
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
|
||||||
#define _glfw_joyGetDevCaps _glfw.win32.winmm.joyGetDevCaps
|
|
||||||
#define _glfw_joyGetPos _glfw.win32.winmm.joyGetPos
|
|
||||||
#define _glfw_joyGetPosEx _glfw.win32.winmm.joyGetPosEx
|
|
||||||
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
||||||
|
|
||||||
|
// xinput.dll function pointer typedefs
|
||||||
|
typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||||
|
typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
|
||||||
|
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
||||||
|
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -217,16 +244,19 @@ typedef struct _GLFWlibraryWin32
|
||||||
// winmm.dll
|
// winmm.dll
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
JOYGETDEVCAPS_T joyGetDevCaps;
|
|
||||||
JOYGETPOS_T joyGetPos;
|
|
||||||
JOYGETPOSEX_T joyGetPosEx;
|
|
||||||
TIMEGETTIME_T timeGetTime;
|
TIMEGETTIME_T timeGetTime;
|
||||||
} winmm;
|
} winmm;
|
||||||
|
|
||||||
// user32.dll
|
// user32.dll
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
SETPROCESSDPIAWARE_T SetProcessDPIAware;
|
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
|
||||||
|
XINPUTGETSTATE_T XInputGetState;
|
||||||
|
} xinput;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
SETPROCESSDPIAWARE_T SetProcessDPIAware;
|
||||||
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
|
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
|
||||||
} user32;
|
} user32;
|
||||||
|
|
||||||
|
|
|
@ -376,10 +376,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||||
|
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
case WM_DISPLAYCHANGE:
|
case WM_DEVICECHANGE:
|
||||||
{
|
{
|
||||||
_glfwInputMonitorChange();
|
if (wParam == DBT_DEVNODES_CHANGED)
|
||||||
return 0;
|
{
|
||||||
|
_glfwInputMonitorChange();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (wParam == DBT_DEVICEARRIVAL)
|
||||||
|
{
|
||||||
|
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||||
|
if (dbh)
|
||||||
|
{
|
||||||
|
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||||
|
_glfwDetectJoystickConnectionWin32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
|
||||||
|
{
|
||||||
|
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||||
|
if (dbh)
|
||||||
|
{
|
||||||
|
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||||
|
_glfwDetectJoystickDisconnectionWin32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user