diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index da2d0bca25b..e1b92f7313c 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -193,6 +193,7 @@ struct JoystickImpl /* Force feedback variables */ struct list ff_effects; int ff_state; + int ff_autocenter; }; static void fake_current_js_state(JoystickImpl *ji); @@ -456,6 +457,10 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION newDevice->ff_state = FF_STATUS_STOPPED; #endif + /* There is no way in linux to query force feedback autocenter status. + Instead, track it with ff_autocenter, and assume it's initialy + enabled. */ + newDevice->ff_autocenter = 1; InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); @@ -663,6 +668,20 @@ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device); } } + else + { + if (!This->ff_autocenter) + { + struct input_event event; + + /* Disable autocenter. */ + event.type = EV_FF; + event.code = FF_AUTOCENTER; + event.value = 0; + if (write(This->joyfd, &event, sizeof(event)) == -1) + ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno)); + } + } return DI_OK; } @@ -679,6 +698,7 @@ static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) res = IDirectInputDevice2AImpl_Unacquire(iface); if (res==DI_OK && This->joyfd!=-1) { effect_list_item *itr; + struct input_event event; /* For each known effect: * - stop it @@ -690,6 +710,16 @@ static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) IDirectInputEffect_Unload(itr->ref); } + /* Enable autocenter. */ + event.type = EV_FF; + event.code = FF_AUTOCENTER; + /* TODO: Read autocenter strengh before disabling it, and use it here + * instead of 0xFFFF (maximum strengh). + */ + event.value = 0xFFFF; + if (write(This->joyfd, &event, sizeof(event)) == -1) + ERR("Failed to set autocenter to %04x: %d %s\n", event.value, errno, strerror(errno)); + close(This->joyfd); This->joyfd = -1; } @@ -919,7 +949,9 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, case (DWORD_PTR)DIPROP_AUTOCENTER: { LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - FIXME("DIPROP_AUTOCENTER(%d)\n", pd->dwData); + TRACE("autocenter(%d)\n", pd->dwData); + This->ff_autocenter = pd->dwData == DIPROPAUTOCENTER_ON; + break; } case (DWORD_PTR)DIPROP_SATURATION: { @@ -1045,6 +1077,14 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); break; } + case (DWORD_PTR) DIPROP_AUTOCENTER: + { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + + pd->dwData = This->ff_autocenter ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF; + TRACE("autocenter(%d)\n", pd->dwData); + break; + } default: return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph); diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c index 133ff58a0af..789317e3a4a 100644 --- a/dlls/dinput/tests/joystick.c +++ b/dlls/dinput/tests/joystick.c @@ -374,6 +374,7 @@ static BOOL CALLBACK EnumJoysticks( if (effect) { DWORD effect_status; + struct DIPROPDWORD diprop_word; hr = IDirectInputEffect_Initialize(effect, hInstance, data->version, &GUID_ConstantForce); @@ -429,6 +430,62 @@ static BOOL CALLBACK EnumJoysticks( ok(hr==DI_OK,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr); todo_wine ok(effect_status!=0,"IDirectInputEffect_GetEffectStatus() reported effect as stopped\n"); + /* Check autocenter status + * State: initialy stopped + * enable + * State: enabled + * acquire + * State: enabled + * unacquire + * State: enabled + * + * IDirectInputDevice2_SetProperty(DIPROP_AUTOCENTER) can only be + * executed when devide is released. + * + * If Executed interactively, user can feel that autocenter is + * only disabled when joystick is acquired. + */ + diprop_word.diph.dwSize = sizeof(diprop_word); + diprop_word.diph.dwHeaderSize = sizeof(diprop_word.diph); + diprop_word.diph.dwObj = 0; + diprop_word.diph.dwHow = DIPH_DEVICE; + hr = IDirectInputDevice_Unacquire(pJoystick); + ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %08x\n", hr); + hr = IDirectInputDevice2_GetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + ok(hr==DI_OK,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr); + ok(diprop_word.dwData==DIPROPAUTOCENTER_ON,"IDirectInputDevice2_GetProperty() reported autocenter as disabled\n"); + diprop_word.dwData = DIPROPAUTOCENTER_OFF; + hr = IDirectInputDevice2_SetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + ok(hr==DI_OK,"IDirectInputDevice2_SetProperty() failed: %08x\n", hr); + hr = IDirectInputDevice2_GetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + ok(hr==DI_OK,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr); + ok(diprop_word.dwData==DIPROPAUTOCENTER_OFF,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n"); + if (winetest_interactive) { + trace("Acquiring in 2s, autocenter will be disabled.\n"); + Sleep(2000); + } + hr = IDirectInputDevice_Acquire(pJoystick); + ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr); + if (winetest_interactive) + trace("Acquired.\n"); + hr = IDirectInputDevice2_GetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + ok(hr==DI_OK,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr); + ok(diprop_word.dwData==DIPROPAUTOCENTER_OFF,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n"); + if (winetest_interactive) { + trace("Releasing in 2s, autocenter will be re-enabled.\n"); + Sleep(2000); + } + hr = IDirectInputDevice_Unacquire(pJoystick); + ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %08x\n", hr); + if (winetest_interactive) + trace("Released\n"); + hr = IDirectInputDevice2_GetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + ok(hr==DI_OK,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr); + ok(diprop_word.dwData==DIPROPAUTOCENTER_OFF,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n"); + hr = IDirectInputDevice_Acquire(pJoystick); + ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr); + hr = IDirectInputDevice2_GetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + ref = IUnknown_Release(effect); ok(ref == 0, "IDirectInputDevice_Release() reference count = %d\n", ref); }