Fix joystick user pointer NULL during disconnect

The joystick code did not distinguish between the allocation status of
the GLFW joystick object and whether it is connection to an OS level
joystick object.

These are now tracked separately.

Fixes #2092

This is adapted to 3.3-stable from
2c204ab52e and
fd7e737216.
This commit is contained in:
Camilla Löwy 2022-05-05 22:23:12 +02:00
parent 6de6446aca
commit 416f7828ff
7 changed files with 41 additions and 32 deletions

View File

@ -136,6 +136,7 @@ video tutorials.
- Kenneth Miller
- Bruce Mitchener
- Jack Moffitt
- Ravi Mohan
- Jeff Molofee
- Alexander Monakov
- Pierre Morel

View File

@ -125,6 +125,7 @@ information on what to include when reporting a bug.
- Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization
- Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization
- Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092)
- [Win32] Bugfix: `Alt+PrtSc` would emit `GLFW_KEY_UNKNOWN` and a different
scancode than `PrtSc` (#1993)
- [Win32] Bugfix: `GLFW_KEY_PAUSE` scancode from `glfwGetKeyScancode` did not

View File

@ -98,8 +98,7 @@ static void closeJoystick(_GLFWjoystick* js)
{
int i;
if (!js->present)
return;
_glfwInputJoystick(js, GLFW_DISCONNECTED);
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
@ -114,7 +113,6 @@ static void closeJoystick(_GLFWjoystick* js)
CFRelease(js->ns.hats);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
// Callback for user-initiated joystick addition
@ -294,9 +292,9 @@ static void removeCallback(void* context,
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (_glfw.joysticks[jid].ns.device == device)
if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].ns.device == device)
{
closeJoystick(_glfw.joysticks + jid);
closeJoystick(&_glfw.joysticks[jid]);
break;
}
}
@ -392,7 +390,10 @@ void _glfwTerminateJoysticksNS(void)
int jid;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid);
{
if (_glfw.joysticks[jid].connected)
closeJoystick(&_glfw.joysticks[jid]);
}
CFRelease(_glfw.ns.hidManager);
_glfw.ns.hidManager = NULL;
@ -470,7 +471,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
}
}
return js->present;
return js->connected;
}
void _glfwPlatformUpdateGamepadGUID(char* guid)

View File

@ -360,6 +360,11 @@ void _glfwInputJoystick(_GLFWjoystick* js, int event)
{
const int jid = (int) (js - _glfw.joysticks);
if (event == GLFW_CONNECTED)
js->connected = GLFW_TRUE;
else if (event == GLFW_DISCONNECTED)
js->connected = GLFW_FALSE;
if (_glfw.callbacks.joystick)
_glfw.callbacks.joystick(jid, event);
}
@ -415,7 +420,7 @@ void _glfwInitGamepadMappings(void)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
if (js->connected)
js->mapping = findValidMapping(js);
}
}
@ -433,7 +438,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (!_glfw.joysticks[jid].present)
if (!_glfw.joysticks[jid].allocated)
break;
}
@ -441,7 +446,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
return NULL;
js = _glfw.joysticks + jid;
js->present = GLFW_TRUE;
js->allocated = GLFW_TRUE;
js->axes = calloc(axisCount, sizeof(float));
js->buttons = calloc(buttonCount + (size_t) hatCount * 4, 1);
js->hats = calloc(hatCount, 1);
@ -944,7 +949,7 @@ GLFWAPI int glfwJoystickPresent(int jid)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return GLFW_FALSE;
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
@ -969,7 +974,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
@ -998,7 +1003,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
@ -1031,7 +1036,7 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
@ -1057,7 +1062,7 @@ GLFWAPI const char* glfwGetJoystickName(int jid)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1082,7 +1087,7 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1101,7 +1106,7 @@ GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
_GLFW_REQUIRE_INIT();
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->allocated)
return;
js->userPointer = pointer;
@ -1117,7 +1122,7 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->allocated)
return NULL;
return js->userPointer;
@ -1183,7 +1188,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
if (js->connected)
js->mapping = findValidMapping(js);
}
@ -1206,7 +1211,7 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return GLFW_FALSE;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1231,7 +1236,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1263,7 +1268,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
}
js = _glfw.joysticks + jid;
if (!js->present)
if (!js->connected)
return GLFW_FALSE;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))

View File

@ -478,7 +478,8 @@ struct _GLFWmapping
//
struct _GLFWjoystick
{
GLFWbool present;
GLFWbool allocated;
GLFWbool connected;
float* axes;
int axisCount;
unsigned char* buttons;

View File

@ -128,7 +128,7 @@ static GLFWbool openJoystickDevice(const char* path)
{
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (!_glfw.joysticks[jid].present)
if (!_glfw.joysticks[jid].connected)
continue;
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
return GLFW_FALSE;
@ -245,9 +245,9 @@ static GLFWbool openJoystickDevice(const char* path)
//
static void closeJoystick(_GLFWjoystick* js)
{
_glfwInputJoystick(js, GLFW_DISCONNECTED);
close(js->linjs.fd);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
// Lexically compare joysticks by name; used by qsort
@ -329,7 +329,7 @@ void _glfwTerminateJoysticksLinux(void)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
if (js->connected)
closeJoystick(js);
}
@ -424,7 +424,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
handleAbsEvent(js, e.code, e.value);
}
return js->present;
return js->connected;
}
void _glfwPlatformUpdateGamepadGUID(char* guid)

View File

@ -256,6 +256,8 @@ static GLFWbool supportsXInput(const GUID* guid)
//
static void closeJoystick(_GLFWjoystick* js)
{
_glfwInputJoystick(js, GLFW_DISCONNECTED);
if (js->win32.device)
{
IDirectInputDevice8_Unacquire(js->win32.device);
@ -263,9 +265,7 @@ static void closeJoystick(_GLFWjoystick* js)
}
free(js->win32.objects);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
// DirectInput device object enumeration callback
@ -357,7 +357,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
js = _glfw.joysticks + jid;
if (js->present)
if (js->connected)
{
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
return DIENUM_CONTINUE;
@ -541,7 +541,7 @@ void _glfwDetectJoystickConnectionWin32(void)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (_glfw.joysticks[jid].present &&
if (_glfw.joysticks[jid].connected &&
_glfw.joysticks[jid].win32.device == NULL &&
_glfw.joysticks[jid].win32.index == index)
{
@ -593,7 +593,7 @@ void _glfwDetectJoystickDisconnectionWin32(void)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
if (js->connected)
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
}
}