diff --git a/.github/workflows/create-test-plan.py b/.github/workflows/create-test-plan.py index a137889c81..8048e2bc32 100755 --- a/.github/workflows/create-test-plan.py +++ b/.github/workflows/create-test-plan.py @@ -381,9 +381,11 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta match spec.msvc_arch: case MsvcArch.X86: job.cflags.append("/clang:-m32") + job.cxxflags.append("/clang:-m32") job.ldflags.append("/MACHINE:X86") case MsvcArch.X64: job.cflags.append("/clang:-m64") + job.cxxflags.append("/clang:-m64") job.ldflags.append("/MACHINE:X64") case _: raise ValueError(f"Unsupported clang-cl architecture (arch={spec.msvc_arch})") diff --git a/CMakeLists.txt b/CMakeLists.txt index 364cb5c0fd..0db59b3eec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1893,11 +1893,13 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) set (USE_POSIX_SPAWN 1) endif() elseif(WINDOWS) + enable_language(CXX) check_c_source_compiles(" #include int main(int argc, char **argv) { return 0; }" HAVE_WIN32_CC) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/windows/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/windows/*.cpp") sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/windows/*.c") sdl_glob_sources("${SDL3_SOURCE_DIR}/src/io/windows/*.c") @@ -2008,6 +2010,7 @@ elseif(WINDOWS) if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_WINDOWS 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/windows/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/windows/*.cpp") CheckOpenVR() @@ -2135,7 +2138,7 @@ elseif(WINDOWS) set(SDL_JOYSTICK_WGI 1) endif() if(HAVE_GAMEINPUT_H) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/gdk/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/gdk/*.cpp") set(SDL_JOYSTICK_GAMEINPUT 1) endif() set(HAVE_SDL_JOYSTICK TRUE) diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index d15619c802..baa2fffe2c 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -645,7 +645,7 @@ - + @@ -710,7 +710,7 @@ - + @@ -891,7 +891,7 @@ - + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 03b5a6a8f8..26f228826c 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -27,7 +27,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -193,7 +193,7 @@ - + diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 738a4110fb..c0a4d86436 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -424,6 +424,16 @@ + + Create + Create + Create + Create + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + @@ -543,7 +553,12 @@ - + + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + @@ -580,7 +595,12 @@ - + + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + @@ -726,7 +746,12 @@ - + + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + $(IntDir)$(TargetName)_cpp.pch + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index a5b201ed6d..2583c9f379 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -537,9 +537,6 @@ events - - events - events @@ -962,6 +959,7 @@ + @@ -1049,7 +1047,7 @@ core - + core\windows @@ -1088,9 +1086,6 @@ events - - events - events @@ -1184,7 +1179,7 @@ joystick\dummy - + joystick\gdk @@ -1367,7 +1362,7 @@ video\windows - + video\windows @@ -1606,11 +1601,12 @@ + + + core\windows + - - - diff --git a/src/core/windows/SDL_gameinput.c b/src/core/windows/SDL_gameinput.cpp similarity index 85% rename from src/core/windows/SDL_gameinput.c rename to src/core/windows/SDL_gameinput.cpp index 9ac5912db9..e2ea3fb4ab 100644 --- a/src/core/windows/SDL_gameinput.c +++ b/src/core/windows/SDL_gameinput.cpp @@ -25,16 +25,11 @@ #include "SDL_windows.h" #include "SDL_gameinput.h" -#ifdef SDL_PLATFORM_WIN32 -#include -// {11BE2A7E-4254-445A-9C09-FFC40F006918} -DEFINE_GUID(SDL_IID_GameInput, 0x11BE2A7E, 0x4254, 0x445A, 0x9C, 0x09, 0xFF, 0xC4, 0x0F, 0x00, 0x69, 0x18); -#endif - static SDL_SharedObject *g_hGameInputDLL; static IGameInput *g_pGameInput; static int g_nGameInputRefCount; + bool SDL_InitGameInput(IGameInput **ppGameInput) { if (g_nGameInputRefCount == 0) { @@ -43,7 +38,7 @@ bool SDL_InitGameInput(IGameInput **ppGameInput) return false; } - typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput); + typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput **gameInput); GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate"); if (!GameInputCreateFunc) { SDL_UnloadObject(g_hGameInputDLL); @@ -58,15 +53,19 @@ bool SDL_InitGameInput(IGameInput **ppGameInput) } #ifdef SDL_PLATFORM_WIN32 - hr = IGameInput_QueryInterface(pGameInput, &SDL_IID_GameInput, (void **)&g_pGameInput); - IGameInput_Release(pGameInput); +#if GAMEINPUT_API_VERSION >= 1 + hr = pGameInput->QueryInterface(IID_IGameInput, (void **)&g_pGameInput); +#else + // We require GameInput v1.1 or newer + hr = E_NOINTERFACE; +#endif + pGameInput->Release(); if (FAILED(hr)) { SDL_UnloadObject(g_hGameInputDLL); return WIN_SetErrorFromHRESULT("GameInput QueryInterface failed", hr); } #else // Assume that the version we get is compatible with the current SDK - // If that isn't the case, define the correct GUID for SDL_IID_GameInput above g_pGameInput = pGameInput; #endif } @@ -85,7 +84,7 @@ void SDL_QuitGameInput(void) --g_nGameInputRefCount; if (g_nGameInputRefCount == 0) { if (g_pGameInput) { - IGameInput_Release(g_pGameInput); + g_pGameInput->Release(); g_pGameInput = NULL; } if (g_hGameInputDLL) { diff --git a/src/core/windows/SDL_gameinput.h b/src/core/windows/SDL_gameinput.h index 0022c0bdde..4d2beb5647 100644 --- a/src/core/windows/SDL_gameinput.h +++ b/src/core/windows/SDL_gameinput.h @@ -25,9 +25,16 @@ #ifdef HAVE_GAMEINPUT_H -#define COBJMACROS #include +#ifndef GAMEINPUT_API_VERSION +#define GAMEINPUT_API_VERSION 0 +#endif + +#if GAMEINPUT_API_VERSION == 1 +using namespace GameInput::v1; +#endif + extern bool SDL_InitGameInput(IGameInput **ppGameInput); extern void SDL_QuitGameInput(void); diff --git a/src/joystick/gdk/SDL_gameinputjoystick.c b/src/joystick/gdk/SDL_gameinputjoystick.cpp similarity index 89% rename from src/joystick/gdk/SDL_gameinputjoystick.c rename to src/joystick/gdk/SDL_gameinputjoystick.cpp index 6cf0a902b7..46d4ecc5f1 100644 --- a/src/joystick/gdk/SDL_gameinputjoystick.c +++ b/src/joystick/gdk/SDL_gameinputjoystick.cpp @@ -24,6 +24,7 @@ #include "../SDL_sysjoystick.h" #include "../usb_ids.h" +#include "../../core/windows/SDL_windows.h" #include "../../core/windows/SDL_gameinput.h" // Default value for SDL_HINT_JOYSTICK_GAMEINPUT @@ -66,7 +67,7 @@ typedef struct joystick_hwdata static GAMEINPUT_InternalList g_GameInputList = { NULL }; static IGameInput *g_pGameInput = NULL; -static GameInputCallbackToken g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE; +static GameInputCallbackToken g_GameInputCallbackToken = 0; static Uint64 g_GameInputTimestampOffset; static bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info) @@ -93,15 +94,22 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) SDL_AssertJoysticksLocked(); - info = IGameInputDevice_GetDeviceInfo(pDevice); - if (info->capabilities & GameInputDeviceCapabilityWireless) { +#if GAMEINPUT_API_VERSION >= 1 + HRESULT hr = pDevice->GetDeviceInfo(&info); + if (FAILED(hr)) { + return WIN_SetErrorFromHRESULT("IGameInputDevice::GetDeviceInfo", hr); + } +#else + info = pDevice->GetDeviceInfo(); +#endif + if (false /*info->capabilities & GameInputDeviceCapabilityWireless*/) { bus = SDL_HARDWARE_BUS_BLUETOOTH; } else { bus = SDL_HARDWARE_BUS_USB; } vendor = info->vendorId; product = info->productId; - version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor; + //version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor; if (SDL_JoystickHandledByAnotherDriver(&SDL_GAMEINPUT_JoystickDriver, vendor, product, version, "")) { return true; @@ -130,18 +138,20 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) // Generate a device path for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) { SDL_snprintf(tmp, SDL_arraysize(tmp), "%02hhX", info->deviceId.value[idx]); - SDL_strlcat(elem->path, tmp, SDL_arraysize(tmp)); - } - - if (info->deviceStrings) { - // In theory we could get the manufacturer and product strings here, but they're NULL for all the controllers I've tested + SDL_strlcat(elem->path, tmp, SDL_arraysize(elem->path)); } +#if GAMEINPUT_API_VERSION >= 1 if (info->displayName) { - // This could give us a product string, but it's NULL for all the controllers I've tested + product_string = info->displayName; } +#else + if (info->displayName) { + product_string = info->displayName->data; + } +#endif - IGameInputDevice_AddRef(pDevice); + pDevice->AddRef(); elem->device = pDevice; elem->name = SDL_CreateJoystickName(vendor, product, manufacturer_string, product_string); elem->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, manufacturer_string, product_string, 'g', 0); @@ -168,7 +178,7 @@ static bool GAMEINPUT_InternalRemoveByIndex(int idx) elem = g_GameInputList.devices[idx]; if (elem) { - IGameInputDevice_Release(elem->device); + elem->device->Release(); SDL_free(elem->name); SDL_free(elem); } @@ -232,10 +242,11 @@ static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback( } static void GAMEINPUT_JoystickDetect(void); +static void GAMEINPUT_JoystickQuit(void); static bool GAMEINPUT_JoystickInit(void) { - HRESULT hR; + HRESULT hr; if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) { return true; @@ -245,21 +256,21 @@ static bool GAMEINPUT_JoystickInit(void) return false; } - hR = IGameInput_RegisterDeviceCallback(g_pGameInput, - NULL, + hr = g_pGameInput->RegisterDeviceCallback(NULL, GameInputKindController, GameInputDeviceConnected, GameInputBlockingEnumeration, NULL, GAMEINPUT_InternalJoystickDeviceCallback, &g_GameInputCallbackToken); - if (FAILED(hR)) { - return SDL_SetError("IGameInput::RegisterDeviceCallback failure with HRESULT of %08lX", hR); + if (FAILED(hr)) { + GAMEINPUT_JoystickQuit(); + return WIN_SetErrorFromHRESULT("IGameInput::RegisterDeviceCallback", hr); } // Calculate the relative offset between SDL timestamps and GameInput timestamps Uint64 now = SDL_GetTicksNS(); - uint64_t timestampUS = IGameInput_GetCurrentTimestamp(g_pGameInput); + uint64_t timestampUS = g_pGameInput->GetCurrentTimestamp(); g_GameInputTimestampOffset = (SDL_NS_TO_US(now) - timestampUS); GAMEINPUT_JoystickDetect(); @@ -292,7 +303,7 @@ static void GAMEINPUT_JoystickDetect(void) elem->isAdded = true; } - if (elem->isDeleteRequested || !(IGameInputDevice_GetDeviceStatus(elem->device) & GameInputDeviceConnected)) { + if (elem->isDeleteRequested || !(elem->device->GetDeviceStatus() & GameInputDeviceConnected)) { SDL_PrivateJoystickRemoved(elem->device_instance); GAMEINPUT_InternalRemoveByIndex(idx--); } @@ -357,6 +368,7 @@ static SDL_JoystickID GAMEINPUT_JoystickGetDeviceInstanceID(int device_index) static void GAMEINPUT_UpdatePowerInfo(SDL_Joystick *joystick, IGameInputDevice *device) { +#if 0 GameInputBatteryState battery_state; SDL_PowerState state; int percent = 0; @@ -385,10 +397,10 @@ static void GAMEINPUT_UpdatePowerInfo(SDL_Joystick *joystick, IGameInputDevice * percent = (int)SDL_roundf((battery_state.remainingCapacity / battery_state.fullChargeCapacity) * 100.0f); } SDL_SendJoystickPowerInfo(joystick, state, percent); +#endif } -#ifdef IGameInput_RegisterSystemButtonCallback - +#if GAMEINPUT_API_VERSION >= 1 static void CALLBACK GAMEINPUT_InternalSystemButtonCallback( _In_ GameInputCallbackToken callbackToken, _In_ void * context, @@ -415,8 +427,7 @@ static void CALLBACK GAMEINPUT_InternalSystemButtonCallback( SDL_UnlockJoysticks(); } } - -#endif // IGameInput_RegisterSystemButtonCallback +#endif // GAMEINPUT_API_VERSION >= 1 static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) { @@ -441,19 +452,15 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nbuttons = 11; joystick->nhats = 1; -#ifdef IGameInput_RegisterSystemButtonCallback +#if GAMEINPUT_API_VERSION >= 1 if (info->supportedSystemButtons != GameInputSystemButtonNone) { if (info->supportedSystemButtons & GameInputSystemButtonShare) { ++joystick->nbuttons; } -#if 1 // The C macro in GameInput.h version 10.0.26100 refers to a focus policy which I guess has been removed from the final API? -#undef IGameInput_RegisterSystemButtonCallback -#define IGameInput_RegisterSystemButtonCallback(This, device, buttonFilter, context, callbackFunc, callbackToken) ((This)->lpVtbl->RegisterSystemButtonCallback(This, device, buttonFilter, context, callbackFunc, callbackToken)) -#endif - IGameInput_RegisterSystemButtonCallback(g_pGameInput, elem->device, (GameInputSystemButtonGuide | GameInputSystemButtonShare), joystick, GAMEINPUT_InternalSystemButtonCallback, &hwdata->system_button_callback_token); + g_pGameInput->RegisterSystemButtonCallback(elem->device, (GameInputSystemButtonGuide | GameInputSystemButtonShare), joystick, GAMEINPUT_InternalSystemButtonCallback, &hwdata->system_button_callback_token); } -#endif // IGameInput_RegisterSystemButtonCallback +#endif // GAMEINPUT_API_VERSION >= 1 } else { joystick->naxes = info->controllerAxisCount; joystick->nbuttons = info->controllerButtonCount; @@ -467,6 +474,7 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, true); } +#if 0 if (info->supportedInput & GameInputKindTouch) { SDL_PrivateJoystickAddTouchpad(joystick, info->touchPointCount); } @@ -482,6 +490,7 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) } else { joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRED; } +#endif return true; } @@ -492,7 +501,7 @@ static bool GAMEINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequenc GameInputRumbleParams *params = &hwdata->rumbleParams; params->lowFrequency = (float)low_frequency_rumble / (float)SDL_MAX_UINT16; params->highFrequency = (float)high_frequency_rumble / (float)SDL_MAX_UINT16; - IGameInputDevice_SetRumbleState(hwdata->devref->device, params); + hwdata->devref->device->SetRumbleState(params); return true; } @@ -503,7 +512,7 @@ static bool GAMEINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left GameInputRumbleParams *params = &hwdata->rumbleParams; params->leftTrigger = (float)left_rumble / (float)SDL_MAX_UINT16; params->rightTrigger = (float)right_rumble / (float)SDL_MAX_UINT16; - IGameInputDevice_SetRumbleState(hwdata->devref->device, params); + hwdata->devref->device->SetRumbleState(params); return true; } @@ -531,15 +540,15 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) IGameInputReading *reading = NULL; Uint64 timestamp; GameInputGamepadState state; - HRESULT hR; + HRESULT hr; - hR = IGameInput_GetCurrentReading(g_pGameInput, info->supportedInput, device, &reading); - if (FAILED(hR)) { + hr = g_pGameInput->GetCurrentReading(info->supportedInput, device, &reading); + if (FAILED(hr)) { // don't SetError here since there can be a legitimate case when there's no reading avail return; } - timestamp = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading) + g_GameInputTimestampOffset); + timestamp = SDL_US_TO_NS(reading->GetTimestamp() + g_GameInputTimestampOffset); if (GAMEINPUT_InternalIsGamepad(info)) { static WORD s_XInputButtons[] = { @@ -557,7 +566,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) }; Uint8 btnidx = 0, hat = 0; - if (IGameInputReading_GetGamepadState(reading, &state)) { + if (reading->GetGamepadState(&state)) { for (btnidx = 0; btnidx < SDL_arraysize(s_XInputButtons); ++btnidx) { WORD button_mask = s_XInputButtons[btnidx]; if (!button_mask) { @@ -599,7 +608,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) if (button_state) { uint32_t i; - uint32_t button_count = IGameInputReading_GetControllerButtonState(reading, info->controllerButtonCount, button_state); + uint32_t button_count = reading->GetControllerButtonState(info->controllerButtonCount, button_state); for (i = 0; i < button_count; ++i) { SDL_SendJoystickButton(timestamp, joystick, (Uint8)i, button_state[i]); } @@ -609,7 +618,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) #define CONVERT_AXIS(v) (Sint16)((v)*65535.0f - 32768.0f) if (axis_state) { uint32_t i; - uint32_t axis_count = IGameInputReading_GetControllerAxisState(reading, info->controllerAxisCount, axis_state); + uint32_t axis_count = reading->GetControllerAxisState(info->controllerAxisCount, axis_state); for (i = 0; i < axis_count; ++i) { SDL_SendJoystickAxis(timestamp, joystick, (Uint8)i, CONVERT_AXIS(axis_state[i])); } @@ -619,7 +628,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) if (switch_state) { uint32_t i; - uint32_t switch_count = IGameInputReading_GetControllerSwitchState(reading, info->controllerSwitchCount, switch_state); + uint32_t switch_count = reading->GetControllerSwitchState(info->controllerSwitchCount, switch_state); for (i = 0; i < switch_count; ++i) { Uint8 hat; switch (switch_state[i]) { @@ -658,6 +667,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) } } +#if 0 if (info->supportedInput & GameInputKindTouch) { GameInputTouchState *touch_state = SDL_stack_alloc(GameInputTouchState, info->touchPointCount); if (touch_state) { @@ -679,8 +689,9 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) // FIXME: How do we interpret the motion data? } } +#endif - IGameInputReading_Release(reading); + reading->Release(); // FIXME: We can poll this at a much lower rate GAMEINPUT_UpdatePowerInfo(joystick, device); @@ -691,7 +702,11 @@ static void GAMEINPUT_JoystickClose(SDL_Joystick* joystick) GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; if (hwdata->system_button_callback_token) { - IGameInput_UnregisterCallback(g_pGameInput, hwdata->system_button_callback_token, 5000); +#if GAMEINPUT_API_VERSION >= 1 + g_pGameInput->UnregisterCallback(hwdata->system_button_callback_token); +#else + g_pGameInput->UnregisterCallback(hwdata->system_button_callback_token, 10000); +#endif } SDL_free(hwdata); @@ -702,8 +717,14 @@ static void GAMEINPUT_JoystickQuit(void) { if (g_pGameInput) { // free the callback - IGameInput_UnregisterCallback(g_pGameInput, g_GameInputCallbackToken, /*timeoutInUs:*/ 10000); - g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE; + if (g_GameInputCallbackToken) { +#if GAMEINPUT_API_VERSION >= 1 + g_pGameInput->UnregisterCallback(g_GameInputCallbackToken); +#else + g_pGameInput->UnregisterCallback(g_GameInputCallbackToken, 10000); +#endif + g_GameInputCallbackToken = 0; + } // free the list while (g_GameInputList.count > 0) { @@ -738,7 +759,7 @@ static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap out->back.kind = EMappingKind_Button; out->back.target = SDL_GAMEPAD_BUTTON_BACK; -#ifdef IGameInput_RegisterSystemButtonCallback +#if GAMEINPUT_API_VERSION >= 1 if (elem->info->supportedSystemButtons & GameInputSystemButtonGuide) { out->guide.kind = EMappingKind_Button; out->guide.target = SDL_GAMEPAD_BUTTON_GUIDE; @@ -748,7 +769,7 @@ static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap out->misc1.kind = EMappingKind_Button; out->misc1.target = SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE; } -#endif +#endif // GAMEINPUT_API_VERSION >= 1 out->start.kind = EMappingKind_Button; out->start.target = SDL_GAMEPAD_BUTTON_START; diff --git a/src/video/windows/SDL_windowsgameinput.c b/src/video/windows/SDL_windowsgameinput.cpp similarity index 81% rename from src/video/windows/SDL_windowsgameinput.c rename to src/video/windows/SDL_windowsgameinput.cpp index 183733a380..7ea77ecc55 100644 --- a/src/video/windows/SDL_windowsgameinput.c +++ b/src/video/windows/SDL_windowsgameinput.cpp @@ -22,16 +22,14 @@ #include "SDL_windowsvideo.h" -// GameInput currently has a bug with keys stuck on focus change, and crashes on initialization on some systems, so we'll disable it until these issues are fixed. -#undef HAVE_GAMEINPUT_H - #ifdef HAVE_GAMEINPUT_H #include "../../core/windows/SDL_gameinput.h" +extern "C" { #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 @@ -75,7 +73,14 @@ static bool GAMEINPUT_InternalAddOrFind(WIN_GameInputData *data, IGameInputDevic const GameInputDeviceInfo *info; bool result = false; - info = IGameInputDevice_GetDeviceInfo(pDevice); +#if GAMEINPUT_API_VERSION >= 1 + HRESULT hr = pDevice->GetDeviceInfo(&info); + if (FAILED(hr)) { + return WIN_SetErrorFromHRESULT("IGameInputDevice_GetDeviceInfo", hr); + } +#else + info = pDevice->GetDeviceInfo(); +#endif SDL_LockMutex(data->lock); { @@ -100,15 +105,11 @@ static bool GAMEINPUT_InternalAddOrFind(WIN_GameInputData *data, IGameInputDevic 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); + pDevice->AddRef(); device->pDevice = pDevice; device->instance_id = SDL_GetNextObjectID(); device->info = info; @@ -147,15 +148,15 @@ static bool GAMEINPUT_InternalRemoveByIndex(WIN_GameInputData *data, int idx) SDL_RemoveKeyboard(device->instance_id, true); } if (device->last_mouse_reading) { - IGameInputReading_Release(device->last_mouse_reading); + device->last_mouse_reading->Release(); device->last_mouse_reading = NULL; } if (device->last_keyboard_reading) { - IGameInputReading_Release(device->last_keyboard_reading); + device->last_keyboard_reading->Release(); device->last_keyboard_reading = NULL; } } - IGameInputDevice_Release(device->pDevice); + device->pDevice->Release(); SDL_free(device->name); SDL_free(device); } @@ -217,6 +218,8 @@ bool WIN_InitGameInput(SDL_VideoDevice *_this) { WIN_GameInputData *data; HRESULT hr; + Uint64 now; + uint64_t timestampUS; bool result = false; if (_this->internal->gameinput_context) { @@ -238,22 +241,21 @@ bool WIN_InitGameInput(SDL_VideoDevice *_this) goto done; } - hr = IGameInput_RegisterDeviceCallback(data->pGameInput, - NULL, - (GameInputKindMouse | GameInputKindKeyboard), - GameInputDeviceConnected, - GameInputBlockingEnumeration, - data, - GAMEINPUT_InternalDeviceCallback, - &data->gameinput_callback_token); + hr = data->pGameInput->RegisterDeviceCallback(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); + WIN_SetErrorFromHRESULT("IGameInput::RegisterDeviceCallback", hr); goto done; } // Calculate the relative offset between SDL timestamps and GameInput timestamps - Uint64 now = SDL_GetTicksNS(); - uint64_t timestampUS = IGameInput_GetCurrentTimestamp(data->pGameInput); + now = SDL_GetTicksNS(); + timestampUS = data->pGameInput->GetCurrentTimestamp(); data->timestamp_offset = (SDL_NS_TO_US(now) - timestampUS); result = true; @@ -268,12 +270,12 @@ done: 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); + if (reading->GetMouseState(&state)) { + Uint64 timestamp = SDL_US_TO_NS(reading->GetTimestamp() + data->timestamp_offset); SDL_MouseID mouseID = device->instance_id; for (int i = 0; i < MAX_GAMEINPUT_BUTTONS; ++i) { - const GameInputMouseButtons mask = (1 << i); + const GameInputMouseButtons mask = GameInputMouseButtons(1 << i); bool down = ((state.buttons & mask) != 0); SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down); } @@ -284,9 +286,8 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind { 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); + if (last_reading->GetMouseState(&last) && reading->GetMouseState(&state)) { + Uint64 timestamp = SDL_US_TO_NS(reading->GetTimestamp() + data->timestamp_offset); SDL_MouseID mouseID = device->instance_id; GameInputMouseState delta; @@ -301,7 +302,7 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind } if (delta.buttons) { for (int i = 0; i < MAX_GAMEINPUT_BUTTONS; ++i) { - const GameInputMouseButtons mask = (1 << i); + const GameInputMouseButtons mask = GameInputMouseButtons(1 << i); if (delta.buttons & mask) { bool down = ((state.buttons & mask) != 0); SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down); @@ -337,7 +338,7 @@ static bool KeysHaveScancode(const GameInputKeyState *keys, uint32_t count, SDL_ 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); + Uint64 timestamp = SDL_US_TO_NS(reading->GetTimestamp() + data->timestamp_offset); SDL_KeyboardID keyboardID = device->instance_id; uint32_t max_keys = device->info->keyboardInfo->maxSimultaneousKeys; @@ -346,7 +347,7 @@ static void GAMEINPUT_InitialKeyboardReading(WIN_GameInputData *data, SDL_Window return; } - uint32_t num_keys = IGameInputReading_GetKeyState(reading, max_keys, keys); + uint32_t num_keys = reading->GetKeyState(max_keys, keys); if (!num_keys) { // FIXME: We probably need to track key state by keyboardID SDL_ResetKeyboard(); @@ -382,7 +383,7 @@ static void DumpKeys(const char *prefix, GameInputKeyState *keys, uint32_t count 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); + Uint64 timestamp = SDL_US_TO_NS(reading->GetTimestamp() + data->timestamp_offset); SDL_KeyboardID keyboardID = device->instance_id; uint32_t max_keys = device->info->keyboardInfo->maxSimultaneousKeys; @@ -394,8 +395,8 @@ static void GAMEINPUT_HandleKeyboardDelta(WIN_GameInputData *data, SDL_Window *w 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); + uint32_t num_last = last_reading->GetKeyState(max_keys, last); + uint32_t num_keys = reading->GetKeyState(max_keys, keys); #ifdef DEBUG_KEYS SDL_Log("Timestamp: %llu", timestamp); DumpKeys("Last keys:", last, num_last); @@ -463,20 +464,20 @@ void WIN_UpdateGameInput(SDL_VideoDevice *_this) 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))) { + while (SUCCEEDED(hr = data->pGameInput->GetNextReading(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->Release(); device->last_mouse_reading = reading; } if (hr != GAMEINPUT_E_READING_NOT_FOUND) { - if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindMouse, device->pDevice, &reading))) { + if (SUCCEEDED(data->pGameInput->GetCurrentReading(GameInputKindMouse, device->pDevice, &reading))) { GAMEINPUT_HandleMouseDelta(data, window, device, device->last_mouse_reading, reading); - IGameInputReading_Release(device->last_mouse_reading); + device->last_mouse_reading->Release(); device->last_mouse_reading = reading; } } } else { - if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindMouse, device->pDevice, &reading))) { + if (SUCCEEDED(data->pGameInput->GetCurrentReading(GameInputKindMouse, device->pDevice, &reading))) { GAMEINPUT_InitialMouseReading(data, window, device, reading); device->last_mouse_reading = reading; } @@ -487,26 +488,26 @@ void WIN_UpdateGameInput(SDL_VideoDevice *_this) 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->Release(); 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))) { + while (SUCCEEDED(hr = data->pGameInput->GetNextReading(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->Release(); device->last_keyboard_reading = reading; } if (hr != GAMEINPUT_E_READING_NOT_FOUND) { - if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindKeyboard, device->pDevice, &reading))) { + if (SUCCEEDED(data->pGameInput->GetCurrentReading(GameInputKindKeyboard, device->pDevice, &reading))) { GAMEINPUT_HandleKeyboardDelta(data, window, device, device->last_keyboard_reading, reading); - IGameInputReading_Release(device->last_keyboard_reading); + device->last_keyboard_reading->Release(); device->last_keyboard_reading = reading; } } } else { - if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindKeyboard, device->pDevice, &reading))) { + if (SUCCEEDED(data->pGameInput->GetCurrentReading(GameInputKindKeyboard, device->pDevice, &reading))) { GAMEINPUT_InitialKeyboardReading(data, window, device, reading); device->last_keyboard_reading = reading; } @@ -534,12 +535,12 @@ bool WIN_UpdateGameInputEnabled(SDL_VideoDevice *_this) GAMEINPUT_Device *device = data->devices[i]; if (device->last_mouse_reading && !raw_mouse_enabled) { - IGameInputReading_Release(device->last_mouse_reading); + device->last_mouse_reading->Release(); device->last_mouse_reading = NULL; } if (device->last_keyboard_reading && !raw_keyboard_enabled) { - IGameInputReading_Release(device->last_keyboard_reading); + device->last_keyboard_reading->Release(); device->last_keyboard_reading = NULL; } } @@ -559,9 +560,13 @@ void WIN_QuitGameInput(SDL_VideoDevice *_this) 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; + if (data->gameinput_callback_token) { +#if GAMEINPUT_API_VERSION >= 1 + data->pGameInput->UnregisterCallback(data->gameinput_callback_token); +#else + data->pGameInput->UnregisterCallback(data->gameinput_callback_token, 10000); +#endif + data->gameinput_callback_token = 0; } // free the list @@ -569,7 +574,7 @@ void WIN_QuitGameInput(SDL_VideoDevice *_this) GAMEINPUT_InternalRemoveByIndex(data, 0); } - IGameInput_Release(data->pGameInput); + data->pGameInput->Release(); data->pGameInput = NULL; } diff --git a/src/video/windows/SDL_windowsgameinput.h b/src/video/windows/SDL_windowsgameinput.h index 561de9c4e0..e6f1afa2d6 100644 --- a/src/video/windows/SDL_windowsgameinput.h +++ b/src/video/windows/SDL_windowsgameinput.h @@ -22,8 +22,17 @@ typedef struct WIN_GameInputData WIN_GameInputData; +// Set up for C function definitions, even when using C++ +#ifdef __cplusplus +extern "C" { +#endif + extern bool WIN_InitGameInput(SDL_VideoDevice *_this); extern bool WIN_UpdateGameInputEnabled(SDL_VideoDevice *_this); extern void WIN_UpdateGameInput(SDL_VideoDevice *_this); extern void WIN_QuitGameInput(SDL_VideoDevice *_this); +// Ends C function definitions when using C++ +#ifdef __cplusplus +} +#endif diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h index 8a0edf5ae0..0e9c50eb86 100644 --- a/src/video/windows/SDL_windowsvideo.h +++ b/src/video/windows/SDL_windowsvideo.h @@ -28,8 +28,10 @@ #include "../SDL_sysvideo.h" #ifdef HAVE_DXGI_H +#ifndef __cplusplus #define CINTERFACE #define COBJMACROS +#endif #include #endif