diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
| commit | 5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch) | |
| tree | 8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/haptic/windows/SDL_windowshaptic.c | |
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/haptic/windows/SDL_windowshaptic.c')
| -rw-r--r-- | contrib/SDL-3.2.8/src/haptic/windows/SDL_windowshaptic.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/haptic/windows/SDL_windowshaptic.c b/contrib/SDL-3.2.8/src/haptic/windows/SDL_windowshaptic.c new file mode 100644 index 0000000..e21ab91 --- /dev/null +++ b/contrib/SDL-3.2.8/src/haptic/windows/SDL_windowshaptic.c | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | #include "SDL_internal.h" | ||
| 22 | |||
| 23 | #ifdef SDL_HAPTIC_DINPUT | ||
| 24 | |||
| 25 | #include "../SDL_syshaptic.h" | ||
| 26 | #include "../../joystick/SDL_sysjoystick.h" // For the real SDL_Joystick | ||
| 27 | #include "../../joystick/windows/SDL_windowsjoystick_c.h" // For joystick hwdata | ||
| 28 | #include "../../joystick/windows/SDL_xinputjoystick_c.h" // For xinput rumble | ||
| 29 | |||
| 30 | #include "SDL_windowshaptic_c.h" | ||
| 31 | #include "SDL_dinputhaptic_c.h" | ||
| 32 | |||
| 33 | // Set up for C function definitions, even when using C++ | ||
| 34 | #ifdef __cplusplus | ||
| 35 | extern "C" { | ||
| 36 | #endif | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Internal stuff. | ||
| 40 | */ | ||
| 41 | SDL_hapticlist_item *SDL_hapticlist = NULL; | ||
| 42 | static SDL_hapticlist_item *SDL_hapticlist_tail = NULL; | ||
| 43 | static int numhaptics = 0; | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Initializes the haptic subsystem. | ||
| 47 | */ | ||
| 48 | bool SDL_SYS_HapticInit(void) | ||
| 49 | { | ||
| 50 | JoyStick_DeviceData *device; | ||
| 51 | |||
| 52 | if (!SDL_DINPUT_HapticInit()) { | ||
| 53 | return false; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* The joystick subsystem will usually be initialized before haptics, | ||
| 57 | * so the initial HapticMaybeAddDevice() calls from the joystick | ||
| 58 | * subsystem will arrive too early to create haptic devices. We will | ||
| 59 | * invoke those callbacks again here to pick up any joysticks that | ||
| 60 | * were added prior to haptics initialization. */ | ||
| 61 | for (device = SYS_Joystick; device; device = device->pNext) { | ||
| 62 | SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice); | ||
| 63 | } | ||
| 64 | |||
| 65 | return true; | ||
| 66 | } | ||
| 67 | |||
| 68 | bool SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item) | ||
| 69 | { | ||
| 70 | if (!SDL_hapticlist_tail) { | ||
| 71 | SDL_hapticlist = SDL_hapticlist_tail = item; | ||
| 72 | } else { | ||
| 73 | SDL_hapticlist_tail->next = item; | ||
| 74 | SDL_hapticlist_tail = item; | ||
| 75 | } | ||
| 76 | |||
| 77 | // Device has been added. | ||
| 78 | ++numhaptics; | ||
| 79 | |||
| 80 | return true; | ||
| 81 | } | ||
| 82 | |||
| 83 | bool SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item) | ||
| 84 | { | ||
| 85 | const bool result = item->haptic ? true : false; | ||
| 86 | if (prev) { | ||
| 87 | prev->next = item->next; | ||
| 88 | } else { | ||
| 89 | SDL_assert(SDL_hapticlist == item); | ||
| 90 | SDL_hapticlist = item->next; | ||
| 91 | } | ||
| 92 | if (item == SDL_hapticlist_tail) { | ||
| 93 | SDL_hapticlist_tail = prev; | ||
| 94 | } | ||
| 95 | --numhaptics; | ||
| 96 | // !!! TODO: Send a haptic remove event? | ||
| 97 | SDL_free(item); | ||
| 98 | return result; | ||
| 99 | } | ||
| 100 | |||
| 101 | int SDL_SYS_NumHaptics(void) | ||
| 102 | { | ||
| 103 | return numhaptics; | ||
| 104 | } | ||
| 105 | |||
| 106 | static SDL_hapticlist_item *HapticByDevIndex(int device_index) | ||
| 107 | { | ||
| 108 | SDL_hapticlist_item *item = SDL_hapticlist; | ||
| 109 | |||
| 110 | if ((device_index < 0) || (device_index >= numhaptics)) { | ||
| 111 | return NULL; | ||
| 112 | } | ||
| 113 | |||
| 114 | while (device_index > 0) { | ||
| 115 | SDL_assert(item != NULL); | ||
| 116 | --device_index; | ||
| 117 | item = item->next; | ||
| 118 | } | ||
| 119 | return item; | ||
| 120 | } | ||
| 121 | |||
| 122 | static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id) | ||
| 123 | { | ||
| 124 | SDL_hapticlist_item *item; | ||
| 125 | for (item = SDL_hapticlist; item; item = item->next) { | ||
| 126 | if (instance_id == item->instance_id) { | ||
| 127 | return item; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | return NULL; | ||
| 131 | } | ||
| 132 | |||
| 133 | SDL_HapticID SDL_SYS_HapticInstanceID(int index) | ||
| 134 | { | ||
| 135 | SDL_hapticlist_item *item = HapticByDevIndex(index); | ||
| 136 | if (item) { | ||
| 137 | return item->instance_id; | ||
| 138 | } | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Return the name of a haptic device, does not need to be opened. | ||
| 144 | */ | ||
| 145 | const char *SDL_SYS_HapticName(int index) | ||
| 146 | { | ||
| 147 | SDL_hapticlist_item *item = HapticByDevIndex(index); | ||
| 148 | return item->name; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* | ||
| 152 | * Opens a haptic device for usage. | ||
| 153 | */ | ||
| 154 | bool SDL_SYS_HapticOpen(SDL_Haptic *haptic) | ||
| 155 | { | ||
| 156 | SDL_hapticlist_item *item = HapticByInstanceID(haptic->instance_id); | ||
| 157 | return SDL_DINPUT_HapticOpen(haptic, item); | ||
| 158 | } | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Opens a haptic device from first mouse it finds for usage. | ||
| 162 | */ | ||
| 163 | int SDL_SYS_HapticMouse(void) | ||
| 164 | { | ||
| 165 | #ifdef SDL_HAPTIC_DINPUT | ||
| 166 | SDL_hapticlist_item *item; | ||
| 167 | int index = 0; | ||
| 168 | |||
| 169 | // Grab the first mouse haptic device we find. | ||
| 170 | for (item = SDL_hapticlist; item; item = item->next) { | ||
| 171 | if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) { | ||
| 172 | return index; | ||
| 173 | } | ||
| 174 | ++index; | ||
| 175 | } | ||
| 176 | #endif // SDL_HAPTIC_DINPUT | ||
| 177 | return -1; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* | ||
| 181 | * Checks to see if a joystick has haptic features. | ||
| 182 | */ | ||
| 183 | bool SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) | ||
| 184 | { | ||
| 185 | if (joystick->driver != &SDL_WINDOWS_JoystickDriver) { | ||
| 186 | return false; | ||
| 187 | } | ||
| 188 | if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) { | ||
| 189 | return true; | ||
| 190 | } | ||
| 191 | return false; | ||
| 192 | } | ||
| 193 | |||
| 194 | /* | ||
| 195 | * Checks to see if the haptic device and joystick are in reality the same. | ||
| 196 | */ | ||
| 197 | bool SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) | ||
| 198 | { | ||
| 199 | if (joystick->driver != &SDL_WINDOWS_JoystickDriver) { | ||
| 200 | return false; | ||
| 201 | } | ||
| 202 | return SDL_DINPUT_JoystickSameHaptic(haptic, joystick); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* | ||
| 206 | * Opens a SDL_Haptic from a SDL_Joystick. | ||
| 207 | */ | ||
| 208 | bool SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) | ||
| 209 | { | ||
| 210 | SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver); | ||
| 211 | |||
| 212 | return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick); | ||
| 213 | } | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Closes the haptic device. | ||
| 217 | */ | ||
| 218 | void SDL_SYS_HapticClose(SDL_Haptic *haptic) | ||
| 219 | { | ||
| 220 | if (haptic->hwdata) { | ||
| 221 | |||
| 222 | // Free effects. | ||
| 223 | SDL_free(haptic->effects); | ||
| 224 | haptic->effects = NULL; | ||
| 225 | haptic->neffects = 0; | ||
| 226 | |||
| 227 | // Clean up | ||
| 228 | SDL_DINPUT_HapticClose(haptic); | ||
| 229 | |||
| 230 | // Free | ||
| 231 | SDL_free(haptic->hwdata); | ||
| 232 | haptic->hwdata = NULL; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * Clean up after system specific haptic stuff | ||
| 238 | */ | ||
| 239 | void SDL_SYS_HapticQuit(void) | ||
| 240 | { | ||
| 241 | SDL_hapticlist_item *item; | ||
| 242 | SDL_hapticlist_item *next = NULL; | ||
| 243 | |||
| 244 | for (item = SDL_hapticlist; item; item = next) { | ||
| 245 | /* Opened and not closed haptics are leaked, this is on purpose. | ||
| 246 | * Close your haptic devices after usage. */ | ||
| 247 | // !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. | ||
| 248 | next = item->next; | ||
| 249 | SDL_free(item->name); | ||
| 250 | SDL_free(item); | ||
| 251 | } | ||
| 252 | |||
| 253 | SDL_DINPUT_HapticQuit(); | ||
| 254 | |||
| 255 | numhaptics = 0; | ||
| 256 | SDL_hapticlist = NULL; | ||
| 257 | SDL_hapticlist_tail = NULL; | ||
| 258 | } | ||
| 259 | |||
| 260 | /* | ||
| 261 | * Creates a new haptic effect. | ||
| 262 | */ | ||
| 263 | bool SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, | ||
| 264 | const SDL_HapticEffect *base) | ||
| 265 | { | ||
| 266 | bool result; | ||
| 267 | |||
| 268 | // Alloc the effect. | ||
| 269 | effect->hweffect = (struct haptic_hweffect *) SDL_calloc(1, sizeof(struct haptic_hweffect)); | ||
| 270 | if (!effect->hweffect) { | ||
| 271 | return false; | ||
| 272 | } | ||
| 273 | |||
| 274 | result = SDL_DINPUT_HapticNewEffect(haptic, effect, base); | ||
| 275 | if (!result) { | ||
| 276 | SDL_free(effect->hweffect); | ||
| 277 | effect->hweffect = NULL; | ||
| 278 | } | ||
| 279 | return result; | ||
| 280 | } | ||
| 281 | |||
| 282 | /* | ||
| 283 | * Updates an effect. | ||
| 284 | */ | ||
| 285 | bool SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data) | ||
| 286 | { | ||
| 287 | return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data); | ||
| 288 | } | ||
| 289 | |||
| 290 | /* | ||
| 291 | * Runs an effect. | ||
| 292 | */ | ||
| 293 | bool SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations) | ||
| 294 | { | ||
| 295 | return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations); | ||
| 296 | } | ||
| 297 | |||
| 298 | /* | ||
| 299 | * Stops an effect. | ||
| 300 | */ | ||
| 301 | bool SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect) | ||
| 302 | { | ||
| 303 | return SDL_DINPUT_HapticStopEffect(haptic, effect); | ||
| 304 | } | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Frees the effect. | ||
| 308 | */ | ||
| 309 | void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect) | ||
| 310 | { | ||
| 311 | SDL_DINPUT_HapticDestroyEffect(haptic, effect); | ||
| 312 | SDL_free(effect->hweffect); | ||
| 313 | effect->hweffect = NULL; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* | ||
| 317 | * Gets the status of a haptic effect. | ||
| 318 | */ | ||
| 319 | int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect) | ||
| 320 | { | ||
| 321 | return SDL_DINPUT_HapticGetEffectStatus(haptic, effect); | ||
| 322 | } | ||
| 323 | |||
| 324 | /* | ||
| 325 | * Sets the gain. | ||
| 326 | */ | ||
| 327 | bool SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain) | ||
| 328 | { | ||
| 329 | return SDL_DINPUT_HapticSetGain(haptic, gain); | ||
| 330 | } | ||
| 331 | |||
| 332 | /* | ||
| 333 | * Sets the autocentering. | ||
| 334 | */ | ||
| 335 | bool SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) | ||
| 336 | { | ||
| 337 | return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter); | ||
| 338 | } | ||
| 339 | |||
| 340 | /* | ||
| 341 | * Pauses the device. | ||
| 342 | */ | ||
| 343 | bool SDL_SYS_HapticPause(SDL_Haptic *haptic) | ||
| 344 | { | ||
| 345 | return SDL_DINPUT_HapticPause(haptic); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Pauses the device. | ||
| 350 | */ | ||
| 351 | bool SDL_SYS_HapticResume(SDL_Haptic *haptic) | ||
| 352 | { | ||
| 353 | return SDL_DINPUT_HapticResume(haptic); | ||
| 354 | } | ||
| 355 | |||
| 356 | /* | ||
| 357 | * Stops all the playing effects on the device. | ||
| 358 | */ | ||
| 359 | bool SDL_SYS_HapticStopAll(SDL_Haptic *haptic) | ||
| 360 | { | ||
| 361 | return SDL_DINPUT_HapticStopAll(haptic); | ||
| 362 | } | ||
| 363 | |||
| 364 | // Ends C function definitions when using C++ | ||
| 365 | #ifdef __cplusplus | ||
| 366 | } | ||
| 367 | #endif | ||
| 368 | |||
| 369 | #endif // SDL_HAPTIC_DINPUT | ||
