mirror of https://github.com/libsdl-org/SDL
Added support for raw mouse and keyboard using GameInput on Windows
Fixes https://github.com/libsdl-org/SDL/issues/10442
This commit is contained in:
parent
8fdca9c691
commit
001dbc5da8
|
@ -573,6 +573,7 @@
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
|
||||||
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsgameinput.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
|
||||||
|
@ -850,6 +851,7 @@
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
|
||||||
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsgameinput.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
|
||||||
|
|
|
@ -217,6 +217,7 @@
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
|
||||||
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsgameinput.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
|
||||||
|
@ -447,6 +448,7 @@
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
|
||||||
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsgameinput.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
|
||||||
|
|
|
@ -479,6 +479,7 @@
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
|
||||||
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsgameinput.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
|
||||||
|
@ -708,6 +709,7 @@
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
|
||||||
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsgameinput.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
|
||||||
|
|
|
@ -684,6 +684,9 @@
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h">
|
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h">
|
||||||
<Filter>video\windows</Filter>
|
<Filter>video\windows</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsgameinput.h">
|
||||||
|
<Filter>video\windows</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h">
|
<ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h">
|
||||||
<Filter>video\windows</Filter>
|
<Filter>video\windows</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1340,6 +1343,9 @@
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c">
|
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c">
|
||||||
<Filter>video\windows</Filter>
|
<Filter>video\windows</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsgameinput.c">
|
||||||
|
<Filter>video\windows</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c">
|
<ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c">
|
||||||
<Filter>video\windows</Filter>
|
<Filter>video\windows</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -3823,6 +3823,20 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP"
|
#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable controlling whether GameInput is used for raw keyboard and mouse on Windows.
|
||||||
|
*
|
||||||
|
* The variable can be set to the following values:
|
||||||
|
*
|
||||||
|
* - "0": GameInput is not used for raw keyboard and mouse events.
|
||||||
|
* - "1": GameInput is used for raw keyboard and mouse events, if available. (default)
|
||||||
|
*
|
||||||
|
* This hint should be set before SDL is initialized.
|
||||||
|
*
|
||||||
|
* \since This hint is available since SDL 3.0.0.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_WINDOWS_GAMEINPUT "SDL_WINDOWS_GAMEINPUT"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variable controlling whether raw keyboard events are used on Windows.
|
* A variable controlling whether raw keyboard events are used on Windows.
|
||||||
*
|
*
|
||||||
|
|
|
@ -2233,6 +2233,10 @@ void WIN_PumpEvents(SDL_VideoDevice *_this)
|
||||||
SDL_Window *focusWindow;
|
SDL_Window *focusWindow;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_this->internal->gameinput_context) {
|
||||||
|
WIN_UpdateGameInput(_this);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_WindowsEnableMessageLoop) {
|
if (g_WindowsEnableMessageLoop) {
|
||||||
SDL_processing_messages = SDL_TRUE;
|
SDL_processing_messages = SDL_TRUE;
|
||||||
|
|
||||||
|
@ -2310,7 +2314,9 @@ void WIN_PumpEvents(SDL_VideoDevice *_this)
|
||||||
/* Update mouse capture */
|
/* Update mouse capture */
|
||||||
WIN_UpdateMouseCapture();
|
WIN_UpdateMouseCapture();
|
||||||
|
|
||||||
|
if (!_this->internal->gameinput_context) {
|
||||||
WIN_CheckKeyboardAndMouseHotplug(_this, SDL_FALSE);
|
WIN_CheckKeyboardAndMouseHotplug(_this, SDL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
WIN_UpdateIMECandidates(_this);
|
WIN_UpdateIMECandidates(_this);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,625 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
#include "SDL_windowsvideo.h"
|
||||||
|
|
||||||
|
#if defined(__has_include) && __has_include(<GameInput.h>)
|
||||||
|
#define HAVE_GAMEINPUT_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GAMEINPUT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#define COBJMACROS
|
||||||
|
#include <GameInput.h>
|
||||||
|
|
||||||
|
#include "../../events/SDL_mouse_c.h"
|
||||||
|
#include "../../events/SDL_keyboard_c.h"
|
||||||
|
#include "../../events/scancodes_windows.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_GAMEINPUT_BUTTONS 7 // GameInputMouseWheelTiltRight is the highest button
|
||||||
|
|
||||||
|
static const Uint8 GAMEINPUT_button_map[MAX_GAMEINPUT_BUTTONS] = {
|
||||||
|
SDL_BUTTON_LEFT,
|
||||||
|
SDL_BUTTON_RIGHT,
|
||||||
|
SDL_BUTTON_MIDDLE,
|
||||||
|
SDL_BUTTON_X1,
|
||||||
|
SDL_BUTTON_X2,
|
||||||
|
6,
|
||||||
|
7
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct GAMEINPUT_Device
|
||||||
|
{
|
||||||
|
IGameInputDevice *pDevice;
|
||||||
|
const GameInputDeviceInfo *info;
|
||||||
|
char *name;
|
||||||
|
Uint32 instance_id; /* generated by SDL */
|
||||||
|
SDL_bool registered;
|
||||||
|
SDL_bool delete_requested;
|
||||||
|
IGameInputReading *last_mouse_reading;
|
||||||
|
IGameInputReading *last_keyboard_reading;
|
||||||
|
} GAMEINPUT_Device;
|
||||||
|
|
||||||
|
struct WIN_GameInputData
|
||||||
|
{
|
||||||
|
void *hGameInputDLL;
|
||||||
|
IGameInput *pGameInput;
|
||||||
|
GameInputCallbackToken gameinput_callback_token;
|
||||||
|
int num_devices;
|
||||||
|
GAMEINPUT_Device **devices;
|
||||||
|
GameInputKind enabled_input;
|
||||||
|
SDL_Mutex *lock;
|
||||||
|
uint64_t timestamp_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int GAMEINPUT_InternalAddOrFind(WIN_GameInputData *data, IGameInputDevice *pDevice)
|
||||||
|
{
|
||||||
|
GAMEINPUT_Device **devicelist = NULL;
|
||||||
|
GAMEINPUT_Device *device = NULL;
|
||||||
|
const GameInputDeviceInfo *info;
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
info = IGameInputDevice_GetDeviceInfo(pDevice);
|
||||||
|
|
||||||
|
SDL_LockMutex(data->lock);
|
||||||
|
{
|
||||||
|
for (int i = 0; i < data->num_devices; ++i) {
|
||||||
|
device = data->devices[i];
|
||||||
|
if (device && device->pDevice == pDevice) {
|
||||||
|
/* we're already added */
|
||||||
|
device->delete_requested = SDL_FALSE;
|
||||||
|
retval = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device = (GAMEINPUT_Device *)SDL_calloc(1, sizeof(*device));
|
||||||
|
if (!device) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
devicelist = (GAMEINPUT_Device **)SDL_realloc(data->devices, (data->num_devices + 1) * sizeof(*devicelist));
|
||||||
|
if (!devicelist) {
|
||||||
|
SDL_free(device);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->deviceStrings) {
|
||||||
|
/* In theory we could get the manufacturer and product strings here, but they're NULL for all the devices I've tested */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->displayName) {
|
||||||
|
/* This could give us a product string, but it's NULL for all the devices I've tested */
|
||||||
|
}
|
||||||
|
|
||||||
|
IGameInputDevice_AddRef(pDevice);
|
||||||
|
device->pDevice = pDevice;
|
||||||
|
device->instance_id = SDL_GetNextObjectID();
|
||||||
|
device->info = info;
|
||||||
|
|
||||||
|
data->devices = devicelist;
|
||||||
|
data->devices[data->num_devices++] = device;
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
SDL_UnlockMutex(data->lock);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GAMEINPUT_InternalRemoveByIndex(WIN_GameInputData *data, int idx)
|
||||||
|
{
|
||||||
|
GAMEINPUT_Device **devicelist = NULL;
|
||||||
|
GAMEINPUT_Device *device;
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
SDL_LockMutex(data->lock);
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= data->num_devices) {
|
||||||
|
retval = SDL_SetError("GAMEINPUT_InternalRemoveByIndex argument idx %d is out of range", idx);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = data->devices[idx];
|
||||||
|
if (device) {
|
||||||
|
if (device->registered) {
|
||||||
|
if (device->info->supportedInput & GameInputKindMouse) {
|
||||||
|
SDL_RemoveMouse(device->instance_id, SDL_TRUE);
|
||||||
|
}
|
||||||
|
if (device->info->supportedInput & GameInputKindKeyboard) {
|
||||||
|
SDL_RemoveKeyboard(device->instance_id, SDL_TRUE);
|
||||||
|
}
|
||||||
|
if (device->last_mouse_reading) {
|
||||||
|
IGameInputReading_Release(device->last_mouse_reading);
|
||||||
|
device->last_mouse_reading = NULL;
|
||||||
|
}
|
||||||
|
if (device->last_keyboard_reading) {
|
||||||
|
IGameInputReading_Release(device->last_keyboard_reading);
|
||||||
|
device->last_keyboard_reading = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IGameInputDevice_Release(device->pDevice);
|
||||||
|
SDL_free(device->name);
|
||||||
|
SDL_free(device);
|
||||||
|
}
|
||||||
|
data->devices[idx] = NULL;
|
||||||
|
|
||||||
|
if (data->num_devices == 1) {
|
||||||
|
/* last element in the list, free the entire list then */
|
||||||
|
SDL_free(data->devices);
|
||||||
|
data->devices = NULL;
|
||||||
|
} else {
|
||||||
|
if (idx != data->num_devices - 1) {
|
||||||
|
size_t bytes = sizeof(*devicelist) * (data->num_devices - idx);
|
||||||
|
SDL_memmove(&data->devices[idx], &data->devices[idx + 1], bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decrement the count and return */
|
||||||
|
retval = data->num_devices--;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
SDL_UnlockMutex(data->lock);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CALLBACK GAMEINPUT_InternalDeviceCallback(
|
||||||
|
_In_ GameInputCallbackToken callbackToken,
|
||||||
|
_In_ void* context,
|
||||||
|
_In_ IGameInputDevice *pDevice,
|
||||||
|
_In_ uint64_t timestamp,
|
||||||
|
_In_ GameInputDeviceStatus currentStatus,
|
||||||
|
_In_ GameInputDeviceStatus previousStatus)
|
||||||
|
{
|
||||||
|
WIN_GameInputData *data = (WIN_GameInputData *)context;
|
||||||
|
int idx = 0;
|
||||||
|
GAMEINPUT_Device *device = NULL;
|
||||||
|
|
||||||
|
if (!pDevice) {
|
||||||
|
/* This should never happen, but ignore it if it does */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentStatus & GameInputDeviceConnected) {
|
||||||
|
GAMEINPUT_InternalAddOrFind(data, pDevice);
|
||||||
|
} else {
|
||||||
|
for (idx = 0; idx < data->num_devices; ++idx) {
|
||||||
|
device = data->devices[idx];
|
||||||
|
if (device && device->pDevice == pDevice) {
|
||||||
|
/* will be deleted on the next Detect call */
|
||||||
|
device->delete_requested = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int WIN_InitGameInput(SDL_VideoDevice *_this)
|
||||||
|
{
|
||||||
|
WIN_GameInputData *data;
|
||||||
|
HRESULT hr;
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
if (_this->internal->gameinput_context) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (WIN_GameInputData *)SDL_calloc(1, sizeof(*data));
|
||||||
|
if (!data) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
_this->internal->gameinput_context = data;
|
||||||
|
|
||||||
|
data->lock = SDL_CreateMutex();
|
||||||
|
if (!data->lock) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->hGameInputDLL = SDL_LoadObject("gameinput.dll");
|
||||||
|
if (!data->hGameInputDLL) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput);
|
||||||
|
GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(data->hGameInputDLL, "GameInputCreate");
|
||||||
|
if (!GameInputCreateFunc) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = GameInputCreateFunc(&data->pGameInput);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_SetError("GameInputCreate failure with HRESULT of %08X", hr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = IGameInput_RegisterDeviceCallback(data->pGameInput,
|
||||||
|
NULL,
|
||||||
|
(GameInputKindMouse | GameInputKindKeyboard),
|
||||||
|
GameInputDeviceConnected,
|
||||||
|
GameInputBlockingEnumeration,
|
||||||
|
data,
|
||||||
|
GAMEINPUT_InternalDeviceCallback,
|
||||||
|
&data->gameinput_callback_token);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_SetError("IGameInput::RegisterDeviceCallback failure with HRESULT of %08X", hr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the relative offset between SDL timestamps and GameInput timestamps
|
||||||
|
Uint64 now = SDL_GetTicksNS();
|
||||||
|
uint64_t timestampUS = IGameInput_GetCurrentTimestamp(data->pGameInput);
|
||||||
|
data->timestamp_offset = (SDL_NS_TO_US(now) - timestampUS);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (retval < 0) {
|
||||||
|
WIN_QuitGameInput(_this);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GAMEINPUT_InitialMouseReading(WIN_GameInputData *data, SDL_Window *window, GAMEINPUT_Device *device, IGameInputReading *reading)
|
||||||
|
{
|
||||||
|
GameInputMouseState state;
|
||||||
|
if (SUCCEEDED(IGameInputReading_GetMouseState(reading, &state))) {
|
||||||
|
Uint64 timestamp = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading) + data->timestamp_offset);
|
||||||
|
SDL_MouseID mouseID = device->instance_id;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_GAMEINPUT_BUTTONS; ++i) {
|
||||||
|
const GameInputMouseButtons mask = (1 << i);
|
||||||
|
SDL_SendMouseButton(timestamp, window, mouseID, (state.buttons & mask) ? SDL_PRESSED : SDL_RELEASED, GAMEINPUT_button_map[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *window, GAMEINPUT_Device *device, IGameInputReading *last_reading, IGameInputReading *reading)
|
||||||
|
{
|
||||||
|
GameInputMouseState last;
|
||||||
|
GameInputMouseState state;
|
||||||
|
if (SUCCEEDED(IGameInputReading_GetMouseState(last_reading, &last)) &&
|
||||||
|
SUCCEEDED(IGameInputReading_GetMouseState(reading, &state))) {
|
||||||
|
Uint64 timestamp = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading) + data->timestamp_offset);
|
||||||
|
SDL_MouseID mouseID = device->instance_id;
|
||||||
|
|
||||||
|
GameInputMouseState delta;
|
||||||
|
delta.buttons = (state.buttons ^ last.buttons);
|
||||||
|
delta.positionX = (state.positionX - last.positionX);
|
||||||
|
delta.positionY = (state.positionY - last.positionY);
|
||||||
|
delta.wheelX = (state.wheelX - last.wheelX);
|
||||||
|
delta.wheelY = (state.wheelY - last.wheelY);
|
||||||
|
|
||||||
|
if (delta.positionX || delta.positionY) {
|
||||||
|
SDL_SendMouseMotion(timestamp, window, mouseID, SDL_TRUE, (float)delta.positionX, (float)delta.positionY);
|
||||||
|
}
|
||||||
|
if (delta.buttons) {
|
||||||
|
for (int i = 0; i < MAX_GAMEINPUT_BUTTONS; ++i) {
|
||||||
|
const GameInputMouseButtons mask = (1 << i);
|
||||||
|
if (delta.buttons & mask) {
|
||||||
|
SDL_SendMouseButton(timestamp, window, mouseID, (state.buttons & mask) ? SDL_PRESSED : SDL_RELEASED, GAMEINPUT_button_map[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (delta.wheelX || delta.wheelY) {
|
||||||
|
float fAmountX = (float)delta.wheelX / WHEEL_DELTA;
|
||||||
|
float fAmountY = (float)delta.wheelY / WHEEL_DELTA;
|
||||||
|
SDL_SendMouseWheel(timestamp, SDL_GetMouseFocus(), device->instance_id, fAmountX, fAmountY, SDL_MOUSEWHEEL_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_Scancode GetScancodeFromKeyState(const GameInputKeyState *state)
|
||||||
|
{
|
||||||
|
Uint8 index = (Uint8)(state->scanCode & 0xFF);
|
||||||
|
if ((state->scanCode & 0xFF00) == 0xE000) {
|
||||||
|
index |= 0x80;
|
||||||
|
}
|
||||||
|
return windows_scancode_table[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool KeysHaveScancode(const GameInputKeyState *keys, uint32_t count, SDL_Scancode scancode)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
|
if (GetScancodeFromKeyState(&keys[i]) == scancode) {
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GAMEINPUT_InitialKeyboardReading(WIN_GameInputData *data, SDL_Window *window, GAMEINPUT_Device *device, IGameInputReading *reading)
|
||||||
|
{
|
||||||
|
Uint64 timestamp = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading) + data->timestamp_offset);
|
||||||
|
SDL_KeyboardID keyboardID = device->instance_id;
|
||||||
|
|
||||||
|
uint32_t max_keys = device->info->keyboardInfo->maxSimultaneousKeys;
|
||||||
|
GameInputKeyState *keys = SDL_stack_alloc(GameInputKeyState, max_keys);
|
||||||
|
if (!keys) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t num_keys = IGameInputReading_GetKeyState(reading, max_keys, keys);
|
||||||
|
if (!num_keys) {
|
||||||
|
// FIXME: We probably need to track key state by keyboardID
|
||||||
|
SDL_ResetKeyboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through and send key up events for any key that's not held down
|
||||||
|
int num_scancodes;
|
||||||
|
const Uint8 *keyboard_state = SDL_GetKeyboardState(&num_scancodes);
|
||||||
|
for (int i = 0; i < num_scancodes; ++i) {
|
||||||
|
if (keyboard_state[i] && !KeysHaveScancode(keys, num_keys, (SDL_Scancode)i)) {
|
||||||
|
SDL_SendKeyboardKey(timestamp, keyboardID, keys[i].scanCode, (SDL_Scancode)i, SDL_RELEASED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through and send key down events for any key that's held down
|
||||||
|
for (uint32_t i = 0; i < num_keys; ++i) {
|
||||||
|
SDL_SendKeyboardKey(timestamp, keyboardID, keys[i].scanCode, GetScancodeFromKeyState(&keys[i]), SDL_PRESSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_KEYS
|
||||||
|
static void DumpKeys(const char *prefix, GameInputKeyState *keys, uint32_t count)
|
||||||
|
{
|
||||||
|
SDL_Log("%s", prefix);
|
||||||
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
|
char str[5];
|
||||||
|
*SDL_UCS4ToUTF8(keys[i].codePoint, str) = '\0';
|
||||||
|
SDL_Log(" Key 0x%.2x (%s)\n", keys[i].scanCode, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // DEBUG_KEYS
|
||||||
|
|
||||||
|
static void GAMEINPUT_HandleKeyboardDelta(WIN_GameInputData *data, SDL_Window *window, GAMEINPUT_Device *device, IGameInputReading *last_reading, IGameInputReading *reading)
|
||||||
|
{
|
||||||
|
Uint64 timestamp = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading) + data->timestamp_offset);
|
||||||
|
SDL_KeyboardID keyboardID = device->instance_id;
|
||||||
|
|
||||||
|
uint32_t max_keys = device->info->keyboardInfo->maxSimultaneousKeys;
|
||||||
|
GameInputKeyState *last = SDL_stack_alloc(GameInputKeyState, max_keys);
|
||||||
|
GameInputKeyState *keys = SDL_stack_alloc(GameInputKeyState, max_keys);
|
||||||
|
if (!last || !keys) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index_last = 0;
|
||||||
|
uint32_t index_keys = 0;
|
||||||
|
uint32_t num_last = IGameInputReading_GetKeyState(last_reading, max_keys, last);
|
||||||
|
uint32_t num_keys = IGameInputReading_GetKeyState(reading, max_keys, keys);
|
||||||
|
#ifdef DEBUG_KEYS
|
||||||
|
SDL_Log("Timestamp: %llu\n", timestamp);
|
||||||
|
DumpKeys("Last keys:", last, num_last);
|
||||||
|
DumpKeys("New keys:", keys, num_keys);
|
||||||
|
#endif
|
||||||
|
while (index_last < num_last || index_keys < num_keys) {
|
||||||
|
if (index_last < num_last && index_keys < num_keys) {
|
||||||
|
if (last[index_last].scanCode == keys[index_keys].scanCode) {
|
||||||
|
// No change
|
||||||
|
++index_last;
|
||||||
|
++index_keys;
|
||||||
|
} else {
|
||||||
|
// This key was released
|
||||||
|
SDL_SendKeyboardKey(timestamp, keyboardID, last[index_last].scanCode, GetScancodeFromKeyState(&last[index_last]), SDL_RELEASED);
|
||||||
|
++index_last;
|
||||||
|
}
|
||||||
|
} else if (index_last < num_last) {
|
||||||
|
// This key was released
|
||||||
|
SDL_SendKeyboardKey(timestamp, keyboardID, last[index_last].scanCode, GetScancodeFromKeyState(&last[index_last]), SDL_RELEASED);
|
||||||
|
++index_last;
|
||||||
|
} else {
|
||||||
|
// This key was pressed
|
||||||
|
SDL_SendKeyboardKey(timestamp, keyboardID, keys[index_keys].scanCode, GetScancodeFromKeyState(&keys[index_keys]), SDL_PRESSED);
|
||||||
|
++index_keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WIN_UpdateGameInput(SDL_VideoDevice *_this)
|
||||||
|
{
|
||||||
|
WIN_GameInputData *data = _this->internal->gameinput_context;
|
||||||
|
|
||||||
|
SDL_LockMutex(data->lock);
|
||||||
|
{
|
||||||
|
// Key events and relative mouse motion both go to the window with keyboard focus
|
||||||
|
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||||
|
|
||||||
|
for (int i = 0; i < data->num_devices; ++i) {
|
||||||
|
GAMEINPUT_Device *device = data->devices[i];
|
||||||
|
IGameInputReading *reading;
|
||||||
|
|
||||||
|
if (!device->registered) {
|
||||||
|
if (device->info->supportedInput & GameInputKindMouse) {
|
||||||
|
SDL_AddMouse(device->instance_id, device->name, SDL_TRUE);
|
||||||
|
}
|
||||||
|
if (device->info->supportedInput & GameInputKindKeyboard) {
|
||||||
|
SDL_AddKeyboard(device->instance_id, device->name, SDL_TRUE);
|
||||||
|
}
|
||||||
|
device->registered = SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->delete_requested) {
|
||||||
|
GAMEINPUT_InternalRemoveByIndex(data, i--);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(device->info->supportedInput & data->enabled_input)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->enabled_input & GameInputKindMouse) {
|
||||||
|
if (device->last_mouse_reading) {
|
||||||
|
HRESULT hr;
|
||||||
|
while (SUCCEEDED(hr = IGameInput_GetNextReading(data->pGameInput, device->last_mouse_reading, GameInputKindMouse, device->pDevice, &reading))) {
|
||||||
|
GAMEINPUT_HandleMouseDelta(data, window, device, device->last_mouse_reading, reading);
|
||||||
|
IGameInputReading_Release(device->last_mouse_reading);
|
||||||
|
device->last_mouse_reading = reading;
|
||||||
|
}
|
||||||
|
if (hr != GAMEINPUT_E_READING_NOT_FOUND) {
|
||||||
|
// The last reading is too old, resynchronize
|
||||||
|
IGameInputReading_Release(device->last_mouse_reading);
|
||||||
|
device->last_mouse_reading = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!device->last_mouse_reading) {
|
||||||
|
if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindMouse, device->pDevice, &reading))) {
|
||||||
|
GAMEINPUT_InitialMouseReading(data, window, device, reading);
|
||||||
|
device->last_mouse_reading = reading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->enabled_input & GameInputKindKeyboard) {
|
||||||
|
if (window->text_input_active) {
|
||||||
|
// Reset raw input while text input is active
|
||||||
|
if (device->last_keyboard_reading) {
|
||||||
|
IGameInputReading_Release(device->last_keyboard_reading);
|
||||||
|
device->last_keyboard_reading = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (device->last_keyboard_reading) {
|
||||||
|
HRESULT hr;
|
||||||
|
while (SUCCEEDED(hr = IGameInput_GetNextReading(data->pGameInput, device->last_keyboard_reading, GameInputKindKeyboard, device->pDevice, &reading))) {
|
||||||
|
GAMEINPUT_HandleKeyboardDelta(data, window, device, device->last_keyboard_reading, reading);
|
||||||
|
IGameInputReading_Release(device->last_keyboard_reading);
|
||||||
|
device->last_keyboard_reading = reading;
|
||||||
|
}
|
||||||
|
if (hr != GAMEINPUT_E_READING_NOT_FOUND) {
|
||||||
|
// The last reading is too old, resynchronize
|
||||||
|
IGameInputReading_Release(device->last_keyboard_reading);
|
||||||
|
device->last_keyboard_reading = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!device->last_keyboard_reading) {
|
||||||
|
if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindKeyboard, device->pDevice, &reading))) {
|
||||||
|
GAMEINPUT_InitialKeyboardReading(data, window, device, reading);
|
||||||
|
device->last_keyboard_reading = reading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_UnlockMutex(data->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WIN_UpdateGameInputEnabled(SDL_VideoDevice *_this)
|
||||||
|
{
|
||||||
|
WIN_GameInputData *data = _this->internal->gameinput_context;
|
||||||
|
SDL_bool raw_mouse_enabled = _this->internal->raw_mouse_enabled;
|
||||||
|
SDL_bool raw_keyboard_enabled = _this->internal->raw_keyboard_enabled;
|
||||||
|
|
||||||
|
SDL_LockMutex(data->lock);
|
||||||
|
{
|
||||||
|
data->enabled_input = (raw_mouse_enabled ? GameInputKindMouse : 0) |
|
||||||
|
(raw_keyboard_enabled ? GameInputKindKeyboard : 0);
|
||||||
|
|
||||||
|
// Reset input if not enabled
|
||||||
|
for (int i = 0; i < data->num_devices; ++i) {
|
||||||
|
GAMEINPUT_Device *device = data->devices[i];
|
||||||
|
|
||||||
|
if (device->last_mouse_reading && !raw_mouse_enabled) {
|
||||||
|
IGameInputReading_Release(device->last_mouse_reading);
|
||||||
|
device->last_mouse_reading = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->last_keyboard_reading && !raw_keyboard_enabled) {
|
||||||
|
IGameInputReading_Release(device->last_keyboard_reading);
|
||||||
|
device->last_keyboard_reading = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_UnlockMutex(data->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WIN_QuitGameInput(SDL_VideoDevice *_this)
|
||||||
|
{
|
||||||
|
WIN_GameInputData *data = _this->internal->gameinput_context;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->pGameInput) {
|
||||||
|
/* free the callback */
|
||||||
|
if (data->gameinput_callback_token != GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE) {
|
||||||
|
IGameInput_UnregisterCallback(data->pGameInput, data->gameinput_callback_token, /*timeoutInUs:*/ 10000);
|
||||||
|
data->gameinput_callback_token = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free the list */
|
||||||
|
while (data->num_devices > 0) {
|
||||||
|
GAMEINPUT_InternalRemoveByIndex(data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGameInput_Release(data->pGameInput);
|
||||||
|
data->pGameInput = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->hGameInputDLL) {
|
||||||
|
SDL_UnloadObject(data->hGameInputDLL);
|
||||||
|
data->hGameInputDLL = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->lock) {
|
||||||
|
SDL_DestroyMutex(data->lock);
|
||||||
|
data->lock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(data);
|
||||||
|
_this->internal->gameinput_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !HAVE_GAMEINPUT_H */
|
||||||
|
|
||||||
|
int WIN_InitGameInput(SDL_VideoDevice* _this)
|
||||||
|
{
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WIN_UpdateGameInputEnabled(SDL_VideoDevice *_this)
|
||||||
|
{
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WIN_UpdateGameInput(SDL_VideoDevice* _this)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WIN_QuitGameInput(SDL_VideoDevice* _this)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GAMEINPUT_H */
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
typedef struct WIN_GameInputData WIN_GameInputData;
|
||||||
|
|
||||||
|
extern int WIN_InitGameInput(SDL_VideoDevice *_this);
|
||||||
|
extern int WIN_UpdateGameInputEnabled(SDL_VideoDevice *_this);
|
||||||
|
extern void WIN_UpdateGameInput(SDL_VideoDevice *_this);
|
||||||
|
extern void WIN_QuitGameInput(SDL_VideoDevice *_this);
|
||||||
|
|
|
@ -203,14 +203,36 @@ int WIN_SetRawMouseEnabled(SDL_VideoDevice *_this, SDL_bool enabled)
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = _this->internal;
|
SDL_VideoData *data = _this->internal;
|
||||||
data->raw_mouse_enabled = enabled;
|
data->raw_mouse_enabled = enabled;
|
||||||
return WIN_UpdateRawInputEnabled(_this);
|
if (data->gameinput_context) {
|
||||||
|
if (WIN_UpdateGameInputEnabled(_this) < 0) {
|
||||||
|
data->raw_mouse_enabled = !enabled;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (WIN_UpdateRawInputEnabled(_this) < 0) {
|
||||||
|
data->raw_mouse_enabled = !enabled;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, SDL_bool enabled)
|
int WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, SDL_bool enabled)
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = _this->internal;
|
SDL_VideoData *data = _this->internal;
|
||||||
data->raw_keyboard_enabled = enabled;
|
data->raw_keyboard_enabled = enabled;
|
||||||
return WIN_UpdateRawInputEnabled(_this);
|
if (data->gameinput_context) {
|
||||||
|
if (WIN_UpdateGameInputEnabled(_this) < 0) {
|
||||||
|
data->raw_keyboard_enabled = !enabled;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (WIN_UpdateRawInputEnabled(_this) < 0) {
|
||||||
|
data->raw_keyboard_enabled = !enabled;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -491,6 +491,10 @@ int WIN_VideoInit(SDL_VideoDevice *_this)
|
||||||
SDL_Log("DPI awareness: %s", WIN_GetDPIAwareness(_this));
|
SDL_Log("DPI awareness: %s", WIN_GetDPIAwareness(_this));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_GAMEINPUT, SDL_TRUE)) {
|
||||||
|
WIN_InitGameInput(_this);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
|
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
/* For Xbox, we just need to create the single display */
|
/* For Xbox, we just need to create the single display */
|
||||||
{
|
{
|
||||||
|
@ -511,7 +515,9 @@ int WIN_VideoInit(SDL_VideoDevice *_this)
|
||||||
WIN_InitKeyboard(_this);
|
WIN_InitKeyboard(_this);
|
||||||
WIN_InitMouse(_this);
|
WIN_InitMouse(_this);
|
||||||
WIN_InitDeviceNotification();
|
WIN_InitDeviceNotification();
|
||||||
|
if (!_this->internal->gameinput_context) {
|
||||||
WIN_CheckKeyboardAndMouseHotplug(_this, SDL_TRUE);
|
WIN_CheckKeyboardAndMouseHotplug(_this, SDL_TRUE);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_AddHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD, UpdateWindowsRawKeyboard, _this);
|
SDL_AddHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD, UpdateWindowsRawKeyboard, _this);
|
||||||
|
@ -530,13 +536,6 @@ void WIN_VideoQuit(SDL_VideoDevice *_this)
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = _this->internal;
|
SDL_VideoData *data = _this->internal;
|
||||||
|
|
||||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
|
||||||
WIN_QuitModes(_this);
|
|
||||||
WIN_QuitDeviceNotification();
|
|
||||||
WIN_QuitKeyboard(_this);
|
|
||||||
WIN_QuitMouse(_this);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_DelHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD, UpdateWindowsRawKeyboard, _this);
|
SDL_DelHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD, UpdateWindowsRawKeyboard, _this);
|
||||||
SDL_DelHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
|
SDL_DelHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
|
||||||
SDL_DelHintCallback(SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS, UpdateWindowsEnableMenuMnemonics, NULL);
|
SDL_DelHintCallback(SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS, UpdateWindowsEnableMenuMnemonics, NULL);
|
||||||
|
@ -544,13 +543,20 @@ void WIN_VideoQuit(SDL_VideoDevice *_this)
|
||||||
|
|
||||||
WIN_SetRawMouseEnabled(_this, SDL_FALSE);
|
WIN_SetRawMouseEnabled(_this, SDL_FALSE);
|
||||||
WIN_SetRawKeyboardEnabled(_this, SDL_FALSE);
|
WIN_SetRawKeyboardEnabled(_this, SDL_FALSE);
|
||||||
|
WIN_QuitGameInput(_this);
|
||||||
|
|
||||||
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
|
WIN_QuitModes(_this);
|
||||||
|
WIN_QuitDeviceNotification();
|
||||||
|
WIN_QuitKeyboard(_this);
|
||||||
|
WIN_QuitMouse(_this);
|
||||||
|
|
||||||
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
|
||||||
if (data->oleinitialized) {
|
if (data->oleinitialized) {
|
||||||
OleUninitialize();
|
OleUninitialize();
|
||||||
data->oleinitialized = SDL_FALSE;
|
data->oleinitialized = SDL_FALSE;
|
||||||
}
|
}
|
||||||
#endif /* !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) */
|
#endif /* !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) */
|
||||||
|
|
||||||
if (data->coinitialized) {
|
if (data->coinitialized) {
|
||||||
WIN_CoUninitialize();
|
WIN_CoUninitialize();
|
||||||
data->coinitialized = SDL_FALSE;
|
data->coinitialized = SDL_FALSE;
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
#include "SDL_windowsclipboard.h"
|
#include "SDL_windowsclipboard.h"
|
||||||
#include "SDL_windowsevents.h"
|
#include "SDL_windowsevents.h"
|
||||||
|
#include "SDL_windowsgameinput.h"
|
||||||
#include "SDL_windowsopengl.h"
|
#include "SDL_windowsopengl.h"
|
||||||
|
|
||||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
|
@ -437,6 +438,8 @@ struct SDL_VideoData
|
||||||
SDL_bool pending_E1_key_sequence;
|
SDL_bool pending_E1_key_sequence;
|
||||||
Uint32 raw_input_enabled;
|
Uint32 raw_input_enabled;
|
||||||
|
|
||||||
|
WIN_GameInputData *gameinput_context;
|
||||||
|
|
||||||
#ifndef SDL_DISABLE_WINDOWS_IME
|
#ifndef SDL_DISABLE_WINDOWS_IME
|
||||||
SDL_bool ime_initialized;
|
SDL_bool ime_initialized;
|
||||||
SDL_bool ime_enabled;
|
SDL_bool ime_enabled;
|
||||||
|
|
Loading…
Reference in New Issue