https://gitlab.winehq.org/wine/wine/-/merge_requests/8773 with some editions.
From: Tyson Whitehead twhitehead@gmail.com
--- dlls/joy.cpl/dinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 68268cbb72c..f090abba3fd 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -166,7 +166,7 @@ static void set_selected_effect( IDirectInputEffect *effect )
EnterCriticalSection( &state_cs ); if ((previous = effect_selected)) IDirectInputEffect_Release( previous ); - if ((effect_selected = effect)) IDirectInput_AddRef( effect ); + if ((effect_selected = effect)) IDirectInputEffect_AddRef( effect ); LeaveCriticalSection( &state_cs ); }
From: Tyson Whitehead twhitehead@gmail.com
--- dlls/joy.cpl/dinput.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index f090abba3fd..071147f4d4b 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -232,7 +232,6 @@ static IDirectInputDevice8W *get_selected_device(void)
static BOOL CALLBACK enum_devices( const DIDEVICEINSTANCEW *instance, void *context ) { - DIDEVCAPS caps = {.dwSize = sizeof(DIDEVCAPS)}; IDirectInput8W *dinput = context; struct device *entry;
@@ -240,7 +239,6 @@ static BOOL CALLBACK enum_devices( const DIDEVICEINSTANCEW *instance, void *cont
IDirectInput8_CreateDevice( dinput, &instance->guidInstance, &entry->device, NULL ); IDirectInputDevice8_SetDataFormat( entry->device, &c_dfDIJoystick2 ); - IDirectInputDevice8_GetCapabilities( entry->device, &caps );
list_add_tail( &devices, &entry->entry );
From: Tyson Whitehead twhitehead@gmail.com
This flag is for passing to Get/SetParameters. It is not a valid setting for the DIEFFECT dwFlags member according to the docs.
Type specific parametrs are indicated by cbTypeSpecificParameters being not 0 and lpvTypeSpecificParametrs being non-NULL. --- dlls/joy.cpl/dinput.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 071147f4d4b..8ec0d59ddab 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -116,13 +116,11 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) { params.cbTypeSpecificParams = sizeof(ramp); params.lpvTypeSpecificParams = &ramp; - params.dwFlags |= DIEP_TYPESPECIFICPARAMS; } else if (IsEqualGUID( &info->guid, &GUID_ConstantForce )) { params.cbTypeSpecificParams = sizeof(constant); params.lpvTypeSpecificParams = &constant; - params.dwFlags |= DIEP_TYPESPECIFICPARAMS; } else if (IsEqualGUID( &info->guid, &GUID_Sine ) || IsEqualGUID( &info->guid, &GUID_Square ) || @@ -132,7 +130,6 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) { params.cbTypeSpecificParams = sizeof(periodic); params.lpvTypeSpecificParams = &periodic; - params.dwFlags |= DIEP_TYPESPECIFICPARAMS; } else if (IsEqualGUID( &info->guid, &GUID_Spring ) || IsEqualGUID( &info->guid, &GUID_Damper ) || @@ -141,7 +138,6 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) { params.cbTypeSpecificParams = sizeof(condition); params.lpvTypeSpecificParams = &condition; - params.dwFlags |= DIEP_TYPESPECIFICPARAMS; }
do hr = IDirectInputDevice2_CreateEffect( device, &info->guid, ¶ms, &effect, NULL );
From: Tyson Whitehead twhitehead@gmail.com
--- dlls/joy.cpl/dinput.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 8ec0d59ddab..8805631451f 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -107,9 +107,6 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) struct effect *entry; HRESULT hr;
- hr = IDirectInputDevice8_Acquire( device ); - if (FAILED(hr)) return DIENUM_CONTINUE; - if (!(entry = calloc( 1, sizeof(*entry) ))) return DIENUM_STOP;
if (IsEqualGUID( &info->guid, &GUID_RampForce )) @@ -202,6 +199,7 @@ static void set_selected_device( IDirectInputDevice8W *device ) if ((previous = device_selected)) { IDirectInputDevice8_SetEventNotification( previous, NULL ); + IDirectInputDevice8_Unacquire( previous ); IDirectInputDevice8_Release( previous ); } if ((device_selected = device)) @@ -230,13 +228,21 @@ static BOOL CALLBACK enum_devices( const DIDEVICEINSTANCEW *instance, void *cont { IDirectInput8W *dinput = context; struct device *entry; + HRESULT hr;
if (!(entry = calloc( 1, sizeof(*entry) ))) return DIENUM_STOP;
- IDirectInput8_CreateDevice( dinput, &instance->guidInstance, &entry->device, NULL ); - IDirectInputDevice8_SetDataFormat( entry->device, &c_dfDIJoystick2 ); + hr = IDirectInput8_CreateDevice( dinput, &instance->guidInstance, &entry->device, NULL ); + if (SUCCEEDED(hr)) hr = IDirectInputDevice8_SetDataFormat( entry->device, &c_dfDIJoystick2 ); + if (SUCCEEDED(hr)) hr = IDirectInputDevice8_SetCooperativeLevel( entry->device, GetAncestor( dialog_hwnd, GA_ROOT ), + DISCL_BACKGROUND | DISCL_EXCLUSIVE );
- list_add_tail( &devices, &entry->entry ); + if (SUCCEEDED(hr)) list_add_tail( &devices, &entry->entry ); + else + { + if (entry->device) IDirectInputDevice8_Release( entry->device ); + free( entry ); + }
return DIENUM_CONTINUE; } @@ -250,7 +256,6 @@ static void clear_devices(void) LIST_FOR_EACH_ENTRY_SAFE( entry, next, &devices, struct device, entry ) { list_remove( &entry->entry ); - IDirectInputDevice8_Unacquire( entry->device ); IDirectInputDevice8_Release( entry->device ); free( entry ); } @@ -645,7 +650,6 @@ static void update_di_effects( HWND hwnd, IDirectInputDevice8W *device )
static void handle_di_effects_change( HWND hwnd ) { - IDirectInputDevice8W *device; struct list *entry; int sel;
@@ -659,14 +663,6 @@ static void handle_di_effects_change( HWND hwnd ) if (!entry) return;
set_selected_effect( LIST_ENTRY( entry, struct effect, entry )->effect ); - - if ((device = get_selected_device())) - { - IDirectInputDevice8_Unacquire( device ); - IDirectInputDevice8_SetCooperativeLevel( device, GetAncestor( hwnd, GA_ROOT ), DISCL_BACKGROUND | DISCL_EXCLUSIVE ); - IDirectInputDevice8_Acquire( device ); - IDirectInputDevice8_Release( device ); - } }
static void create_device_views( HWND hwnd )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/joy.cpl/dinput.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 8805631451f..3a31591216b 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -163,12 +163,15 @@ static void set_selected_effect( IDirectInputEffect *effect ) LeaveCriticalSection( &state_cs ); }
-static IDirectInputEffect *get_selected_effect(void) +static IDirectInputEffect *get_selected_effect( DIJOYSTATE2 *state ) { + IDirectInputDevice8W *device; IDirectInputEffect *effect;
EnterCriticalSection( &state_cs ); - if ((effect = effect_selected)) IDirectInputEffect_AddRef( effect ); + if (!(device = device_selected)) effect = NULL; + else if (FAILED(IDirectInputDevice8_GetDeviceState( device, sizeof(*state), state ))) effect = NULL; + else if ((effect = effect_selected)) IDirectInputEffect_AddRef( effect ); LeaveCriticalSection( &state_cs );
return effect; @@ -269,12 +272,13 @@ static DWORD WINAPI input_thread( void *param ) { IDirectInputEffect *effect; DIJOYSTATE2 state = {0}; - unsigned int i;
SendMessageW( dialog_hwnd, WM_USER, 0, 0 );
- if ((effect = get_selected_effect())) + if ((effect = get_selected_effect( &state ))) { + static const BYTE empty[sizeof(state.rgbButtons)] = {0}; + BOOL pressed = memcmp( empty, state.rgbButtons, sizeof(state.rgbButtons) ); DWORD flags = DIEP_AXES | DIEP_DIRECTION | DIEP_NORESTART; LONG direction[3] = {0}; DWORD axes[3] = {0}; @@ -291,14 +295,10 @@ static DWORD WINAPI input_thread( void *param ) params.rgdwAxes[0] = state.lX; params.rgdwAxes[1] = state.lY;
- for (i = 0; i < ARRAY_SIZE(state.rgbButtons); i++) + if (pressed) { - if (state.rgbButtons[i]) - { - IDirectInputEffect_SetParameters( effect, ¶ms, flags ); - IDirectInputEffect_Start( effect, 1, 0 ); - break; - } + IDirectInputEffect_SetParameters( effect, ¶ms, flags ); + IDirectInputEffect_Start( effect, 1, 0 ); }
IDirectInputEffect_Release( effect );
From: Tyson Whitehead twhitehead@gmail.com
--- dlls/joy.cpl/dinput.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 3a31591216b..8f172879e46 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -272,6 +272,7 @@ static DWORD WINAPI input_thread( void *param ) { IDirectInputEffect *effect; DIJOYSTATE2 state = {0}; + HRESULT hr;
SendMessageW( dialog_hwnd, WM_USER, 0, 0 );
@@ -279,25 +280,20 @@ static DWORD WINAPI input_thread( void *param ) { static const BYTE empty[sizeof(state.rgbButtons)] = {0}; BOOL pressed = memcmp( empty, state.rgbButtons, sizeof(state.rgbButtons) ); - DWORD flags = DIEP_AXES | DIEP_DIRECTION | DIEP_NORESTART; - LONG direction[3] = {0}; - DWORD axes[3] = {0}; + LONG direction[2] = {state.lX - 32768, state.lY - 32768}; DIEFFECT params = { .dwSize = sizeof(DIEFFECT), - .dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS, + .dwFlags = DIEFF_CARTESIAN, .rglDirection = direction, - .rgdwAxes = axes, - .cAxes = 3, + .cAxes = 2, };
- IDirectInputEffect_GetParameters( effect, ¶ms, flags ); - params.rgdwAxes[0] = state.lX; - params.rgdwAxes[1] = state.lY; - if (pressed) { - IDirectInputEffect_SetParameters( effect, ¶ms, flags ); + do hr = IDirectInputEffect_SetParameters( effect, ¶ms, DIEP_DIRECTION | DIEP_NORESTART ); + while (FAILED(hr) && --params.cAxes); + IDirectInputEffect_Start( effect, 1, 0 ); }
From: Tyson Whitehead twhitehead@gmail.com
--- dlls/joy.cpl/dinput.c | 28 ++++++++++++++++++++++++++-- dlls/joy.cpl/joy.rc | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 8f172879e46..f6cd7f5c44e 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -77,7 +77,7 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) { .dwSize = sizeof(DIEFFECT), .dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS, - .dwDuration = 2 * DI_SECONDS, + .dwDuration = INFINITE, .dwGain = DI_FFNOMINALMAX, .rglDirection = direction, .rgdwAxes = axes, @@ -112,6 +112,7 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) if (IsEqualGUID( &info->guid, &GUID_RampForce )) { params.cbTypeSpecificParams = sizeof(ramp); + params.dwDuration = 2 * DI_SECONDS; params.lpvTypeSpecificParams = &ramp; } else if (IsEqualGUID( &info->guid, &GUID_ConstantForce )) @@ -267,6 +268,7 @@ static void clear_devices(void) static DWORD WINAPI input_thread( void *param ) { HANDLE events[2] = {param, state_event}; + IDirectInputEffect *playing = NULL;
while (WaitForMultipleObjects( 2, events, FALSE, INFINITE ) != 0) { @@ -289,16 +291,38 @@ static DWORD WINAPI input_thread( void *param ) .cAxes = 2, };
- if (pressed) + if (playing && (!pressed || playing != effect)) + { + IDirectInputEffect_Stop( playing ); + IDirectInputEffect_Release( playing ); + playing = NULL; + } + + if (pressed && !playing) { do hr = IDirectInputEffect_SetParameters( effect, ¶ms, DIEP_DIRECTION | DIEP_NORESTART ); while (FAILED(hr) && --params.cAxes);
IDirectInputEffect_Start( effect, 1, 0 ); + IDirectInputEffect_AddRef( effect ); + playing = effect; }
IDirectInputEffect_Release( effect ); } + else if (playing) + { + IDirectInputEffect_Stop( playing ); + IDirectInputEffect_Release( playing ); + playing = NULL; + } + } + + if (playing) + { + IDirectInputEffect_Stop( playing ); + IDirectInputEffect_Release( playing ); + playing = NULL; }
return 0; diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc index 1eb62d86ab3..c98bbe886c4 100644 --- a/dlls/joy.cpl/joy.rc +++ b/dlls/joy.cpl/joy.rc @@ -63,7 +63,7 @@ FONT 8, "Ms Shell Dlg" GROUPBOX "Buttons", IDC_DI_BUTTONS, 15, 100, 291, 86 LTEXT "Force Feedback Effect", IDC_STATIC, 15, 196, 291, 10 LISTBOX IDC_DI_EFFECTS, 15, 206, 291, 54, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY - LTEXT "Press any button in the controller to activate the chosen effect. The effect direction can be changed with the controller axis.", + LTEXT "Hold any button in the controller to play the chosen effect. The effect direction can be changed with the controller axis.", IDC_STATIC, 15, 260, 291, 25 }
From: Tyson Whitehead twhitehead@gmail.com
It makes it hard to feel some effects. --- dlls/joy.cpl/dinput.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index f6cd7f5c44e..fa3b067c382 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -232,6 +232,16 @@ static BOOL CALLBACK enum_devices( const DIDEVICEINSTANCEW *instance, void *cont { IDirectInput8W *dinput = context; struct device *entry; + DIPROPDWORD ac_prop = + { + .diph = + { + .dwSize = sizeof(DIPROPDWORD), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + .dwData = DIPROPAUTOCENTER_OFF, + }; HRESULT hr;
if (!(entry = calloc( 1, sizeof(*entry) ))) return DIENUM_STOP; @@ -240,6 +250,7 @@ static BOOL CALLBACK enum_devices( const DIDEVICEINSTANCEW *instance, void *cont if (SUCCEEDED(hr)) hr = IDirectInputDevice8_SetDataFormat( entry->device, &c_dfDIJoystick2 ); if (SUCCEEDED(hr)) hr = IDirectInputDevice8_SetCooperativeLevel( entry->device, GetAncestor( dialog_hwnd, GA_ROOT ), DISCL_BACKGROUND | DISCL_EXCLUSIVE ); + if (SUCCEEDED(hr)) hr = IDirectInputDevice8_SetProperty( entry->device, DIPROP_AUTOCENTER, &ac_prop.diph );
if (SUCCEEDED(hr)) list_add_tail( &devices, &entry->entry ); else
From: Tyson Whitehead twhitehead@gmail.com
Wore general as will apply type specific parametrs to all effects that are of the given type and not just specific types. --- dlls/joy.cpl/dinput.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index fa3b067c382..925c6d0038c 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -109,33 +109,25 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context )
if (!(entry = calloc( 1, sizeof(*entry) ))) return DIENUM_STOP;
- if (IsEqualGUID( &info->guid, &GUID_RampForce )) + switch (DIEFT_GETTYPE( info->dwEffType )) { + case DIEFT_RAMPFORCE: params.cbTypeSpecificParams = sizeof(ramp); params.dwDuration = 2 * DI_SECONDS; params.lpvTypeSpecificParams = &ramp; - } - else if (IsEqualGUID( &info->guid, &GUID_ConstantForce )) - { + break; + case DIEFT_CONSTANTFORCE: params.cbTypeSpecificParams = sizeof(constant); params.lpvTypeSpecificParams = &constant; - } - else if (IsEqualGUID( &info->guid, &GUID_Sine ) || - IsEqualGUID( &info->guid, &GUID_Square ) || - IsEqualGUID( &info->guid, &GUID_Triangle ) || - IsEqualGUID( &info->guid, &GUID_SawtoothUp ) || - IsEqualGUID( &info->guid, &GUID_SawtoothDown )) - { + break; + case DIEFT_PERIODIC: params.cbTypeSpecificParams = sizeof(periodic); params.lpvTypeSpecificParams = &periodic; - } - else if (IsEqualGUID( &info->guid, &GUID_Spring ) || - IsEqualGUID( &info->guid, &GUID_Damper ) || - IsEqualGUID( &info->guid, &GUID_Inertia ) || - IsEqualGUID( &info->guid, &GUID_Friction )) - { + break; + case DIEFT_CONDITION: params.cbTypeSpecificParams = sizeof(condition); params.lpvTypeSpecificParams = &condition; + break; }
do hr = IDirectInputDevice2_CreateEffect( device, &info->guid, ¶ms, &effect, NULL );
Tried it. Works good. :thumbsup:
Thanks for catching the missing `free` I introduced into the effect enumeration too!
This merge request was approved by Rémi Bernon.