Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device.c | 23 ------ dlls/dinput/keyboard.c | 93 ++++++++++++++++------- dlls/dinput/mouse.c | 142 ++++++++++++++++++++++++++++++------ dlls/dinput8/tests/device.c | 9 +-- 4 files changed, 187 insertions(+), 80 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index bee9ac8ab45..74f687c5966 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1158,29 +1158,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects( IDirectInputDevice8W *iface if (flags & ~(DIDFT_AXIS | DIDFT_POV | DIDFT_BUTTON | DIDFT_NODATA | DIDFT_COLLECTION)) return DIERR_INVALIDPARAM;
- if (!impl->vtbl->enum_objects) - { - DIDEVICEOBJECTINSTANCEW ddoi; - DWORD i; - - /* Only the fields till dwFFMaxForce are relevant */ - memset( &ddoi, 0, sizeof(ddoi) ); - ddoi.dwSize = FIELD_OFFSET( DIDEVICEOBJECTINSTANCEW, dwFFMaxForce ); - - for (i = 0; i < impl->data_format.wine_df->dwNumObjs; i++) - { - LPDIOBJECTDATAFORMAT odf = dataformat_to_odf( impl->data_format.wine_df, i ); - - if (flags != DIDFT_ALL && !(flags & DIDFT_GETTYPE( odf->dwType ))) continue; - if (IDirectInputDevice_GetObjectInfo( iface, &ddoi, odf->dwType, DIPH_BYID ) != DI_OK) - continue; - - if (callback( &ddoi, context ) != DIENUM_CONTINUE) break; - } - - return DI_OK; - } - if (flags == DIDFT_ALL || (flags & DIDFT_AXIS)) { hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, callback, context ); diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index a296ebc98ce..50e292abaad 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -196,14 +196,11 @@ static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, SysKeyboar { BYTE subtype = get_keyboard_subtype(); SysKeyboardImpl* newDevice; - LPDIDATAFORMAT df = NULL; - int i, idx = 0; HRESULT hr;
if (FAILED(hr = direct_input_device_alloc( sizeof(SysKeyboardImpl), &SysKeyboardWvt, &keyboard_internal_vtbl, rguid, dinput, (void **)&newDevice ))) return hr; - df = newDevice->base.data_format.wine_df; newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
fill_keyboard_dideviceinstanceW( &newDevice->base.instance, newDevice->base.dinput->dwVersion, subtype ); @@ -211,33 +208,14 @@ static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, SysKeyboar newDevice->base.caps.dwFirmwareRevision = 100; newDevice->base.caps.dwHardwareRevision = 100;
- /* Create copy of default data format */ - memcpy(df, &c_dfDIKeyboard, c_dfDIKeyboard.dwSize); - if (!(df->rgodf = malloc( df->dwNumObjs * df->dwObjSize ))) goto failed; - - for (i = 0; i < df->dwNumObjs; i++) + if (FAILED(hr = direct_input_device_init( &newDevice->base.IDirectInputDevice8W_iface ))) { - char buf[MAX_PATH]; - BYTE dik_code; - - if (!GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), buf, sizeof(buf))) - continue; - - dik_code = map_dik_code( i, 0, subtype, dinput->dwVersion ); - memcpy(&df->rgodf[idx], &c_dfDIKeyboard.rgodf[dik_code], df->dwObjSize); - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(dik_code) | DIDFT_PSHBUTTON; + IDirectInputDevice_Release( &newDevice->base.IDirectInputDevice8W_iface ); + return hr; } - df->dwNumObjs = idx; - newDevice->base.caps.dwButtons = idx;
*out = newDevice; return DI_OK; - -failed: - if (df) free( df->rgodf ); - free( df ); - free( newDevice ); - return DIERR_OUTOFMEMORY; }
static HRESULT keyboarddev_create_device( IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDevice8W **out ) @@ -407,12 +385,75 @@ static HRESULT keyboard_internal_unacquire( IDirectInputDevice8W *iface ) return DI_OK; }
+static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + if (flags != DIDFT_ALL && !(flags & DIDFT_GETTYPE( instance->dwType ))) return DIENUM_CONTINUE; + + switch (filter->dwHow) + { + case DIPH_DEVICE: + return callback( instance, data ); + case DIPH_BYOFFSET: + if (filter->dwObj != instance->dwOfs) return DIENUM_CONTINUE; + return callback( instance, data ); + case DIPH_BYID: + if ((filter->dwObj & 0x00ffffff) != (instance->dwType & 0x00ffffff)) return DIENUM_CONTINUE; + return callback( instance, data ); + } + + return DIENUM_CONTINUE; +} + +static HRESULT keyboard_internal_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *header, DWORD flags, + LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context ) +{ + SysKeyboardImpl *impl = impl_from_IDirectInputDevice8W( iface ); + BYTE subtype = GET_DIDEVICE_SUBTYPE( impl->base.instance.dwDevType ); + DIDEVICEOBJECTINSTANCEW instance = + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Key, + .dwOfs = DIK_ESCAPE, + .dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( DIK_ESCAPE ), + }; + DIDATAFORMAT *format = impl->base.data_format.wine_df; + int *offsets = impl->base.data_format.offsets; + DIPROPHEADER filter = *header; + DWORD i, dik; + BOOL ret; + + if (header->dwHow != DIPH_DEVICE && header->dwHow != DIPH_BYOFFSET && header->dwHow != DIPH_BYID) + return DIERR_UNSUPPORTED; + + if (filter.dwHow == DIPH_BYOFFSET) + { + if (!offsets) return DIENUM_CONTINUE; + for (i = 0; i < format->dwNumObjs; ++i) + if (offsets[i] == filter.dwObj) break; + if (i == format->dwNumObjs) return DIENUM_CONTINUE; + filter.dwObj = format->rgodf[i].dwOfs; + } + + for (i = 0; i < 512; ++i) + { + if (!GetKeyNameTextW( i << 16, instance.tszName, ARRAY_SIZE(instance.tszName) )) continue; + if (!(dik = map_dik_code( i, 0, subtype, impl->base.dinput->dwVersion ))) continue; + instance.dwOfs = dik; + instance.dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( dik ); + ret = try_enum_object( &filter, flags, callback, &instance, context ); + if (ret != DIENUM_CONTINUE) return DIENUM_STOP; + } + + return DIENUM_CONTINUE; +} + static const struct dinput_device_vtbl keyboard_internal_vtbl = { NULL, keyboard_internal_acquire, keyboard_internal_unacquire, - NULL, + keyboard_internal_enum_objects, };
static const IDirectInputDevice8WVtbl SysKeyboardWvt = diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index ea3fcbb5581..cdbdd083c00 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -138,8 +138,6 @@ static HRESULT mousedev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEIN static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, SysMouseImpl **out ) { SysMouseImpl* newDevice; - LPDIDATAFORMAT df = NULL; - unsigned i; WCHAR buffer[20]; HKEY hkey, appkey; HRESULT hr; @@ -147,13 +145,10 @@ static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, SysMouseIm if (FAILED(hr = direct_input_device_alloc( sizeof(SysMouseImpl), &SysMouseWvt, &mouse_internal_vtbl, rguid, dinput, (void **)&newDevice ))) return hr; - df = newDevice->base.data_format.wine_df; newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
fill_mouse_dideviceinstanceW( &newDevice->base.instance, newDevice->base.dinput->dwVersion ); newDevice->base.caps.dwDevType = newDevice->base.instance.dwDevType; - newDevice->base.caps.dwAxes = 3; - newDevice->base.caps.dwButtons = 8; newDevice->base.caps.dwFirmwareRevision = 100; newDevice->base.caps.dwHardwareRevision = 100; newDevice->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND; @@ -167,17 +162,11 @@ static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, SysMouseIm if (appkey) RegCloseKey(appkey); if (hkey) RegCloseKey(hkey);
- /* Create copy of default data format */ - memcpy(df, &c_dfDIMouse2, c_dfDIMouse2.dwSize); - if (!(df->rgodf = malloc( df->dwNumObjs * df->dwObjSize ))) goto failed; - memcpy(df->rgodf, c_dfDIMouse2.rgodf, df->dwNumObjs * df->dwObjSize); - - /* Because we don't do any detection yet just modify instance and type */ - for (i = 0; i < df->dwNumObjs; i++) - if (DIDFT_GETTYPE(df->rgodf[i].dwType) & DIDFT_AXIS) - df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_RELAXIS; - else - df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON; + if (FAILED(hr = direct_input_device_init( &newDevice->base.IDirectInputDevice8W_iface ))) + { + IDirectInputDevice_Release( &newDevice->base.IDirectInputDevice8W_iface ); + return hr; + }
if (dinput->dwVersion >= 0x0800) { @@ -188,12 +177,6 @@ static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, SysMouseIm
*out = newDevice; return DI_OK; - -failed: - if (df) free( df->rgodf ); - free( df ); - free( newDevice ); - return DIERR_OUTOFMEMORY; }
static HRESULT mousedev_create_device( IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDevice8W **out ) @@ -663,12 +646,125 @@ static HRESULT mouse_internal_unacquire( IDirectInputDevice8W *iface ) return DI_OK; }
+static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + if (flags != DIDFT_ALL && !(flags & DIDFT_GETTYPE( instance->dwType ))) return DIENUM_CONTINUE; + + switch (filter->dwHow) + { + case DIPH_DEVICE: + return callback( instance, data ); + case DIPH_BYOFFSET: + if (filter->dwObj != instance->dwOfs) return DIENUM_CONTINUE; + return callback( instance, data ); + case DIPH_BYID: + if ((filter->dwObj & 0x00ffffff) != (instance->dwType & 0x00ffffff)) return DIENUM_CONTINUE; + return callback( instance, data ); + } + + return DIENUM_CONTINUE; +} + +static HRESULT mouse_internal_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *header, DWORD flags, + LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context ) +{ + DIDEVICEOBJECTINSTANCEW instances[] = + { + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_XAxis, + .dwOfs = DIMOFS_X, + .dwType = DIDFT_RELAXIS|DIDFT_MAKEINSTANCE(0), + .dwFlags = DIDOI_ASPECTPOSITION, + .tszName = L"X-axis", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_YAxis, + .dwOfs = DIMOFS_Y, + .dwType = DIDFT_RELAXIS|DIDFT_MAKEINSTANCE(1), + .dwFlags = DIDOI_ASPECTPOSITION, + .tszName = L"Y-axis", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_ZAxis, + .dwOfs = DIMOFS_Z, + .dwType = DIDFT_RELAXIS|DIDFT_MAKEINSTANCE(2), + .dwFlags = DIDOI_ASPECTPOSITION, + .tszName = L"Wheel", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = DIMOFS_BUTTON0, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(3), + .tszName = L"Button 0", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = DIMOFS_BUTTON1, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(4), + .tszName = L"Button 1", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = DIMOFS_BUTTON2, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(5), + .tszName = L"Button 2", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = DIMOFS_BUTTON3, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(6), + .tszName = L"Button 3", + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = DIMOFS_BUTTON4, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(7), + .tszName = L"Button 4", + }, + }; + SysMouseImpl *impl = impl_from_IDirectInputDevice8W( iface ); + DIDATAFORMAT *format = impl->base.data_format.wine_df; + int *offsets = impl->base.data_format.offsets; + DIPROPHEADER filter = *header; + BOOL ret; + DWORD i; + + if (header->dwHow != DIPH_DEVICE && header->dwHow != DIPH_BYOFFSET && header->dwHow != DIPH_BYID) + return DIERR_UNSUPPORTED; + + if (filter.dwHow == DIPH_BYOFFSET) + { + if (!offsets) return DIENUM_CONTINUE; + for (i = 0; i < format->dwNumObjs; ++i) + if (offsets[i] == filter.dwObj) break; + if (i == format->dwNumObjs) return DIENUM_CONTINUE; + filter.dwObj = format->rgodf[i].dwOfs; + } + + for (i = 0; i < ARRAY_SIZE(instances); ++i) + { + ret = try_enum_object( &filter, flags, callback, instances + i, context ); + if (ret != DIENUM_CONTINUE) return DIENUM_STOP; + } + + return DIENUM_CONTINUE; +} + static const struct dinput_device_vtbl mouse_internal_vtbl = { NULL, mouse_internal_acquire, mouse_internal_unacquire, - NULL, + mouse_internal_enum_objects, };
static const IDirectInputDevice8WVtbl SysMouseWvt = diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 1819d597a6b..ca8a7d89bc8 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -1068,7 +1068,6 @@ static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *ar
winetest_push_context( "obj[%d]", params->index );
- todo_wine check_member( *obj, *exp, "%u", dwSize ); check_member_guid( *obj, *exp, guidType ); todo_wine_if( todo->offset ) @@ -1183,11 +1182,7 @@ static void test_mouse_info(void) .tszName = L"Button 4", }, }; - struct check_objects_todos todo_objects[ARRAY_SIZE(expect_objects)] = - { - {.name = TRUE}, - {.name = TRUE}, - }; + struct check_objects_todos todo_objects[ARRAY_SIZE(expect_objects)] = {{0}}; struct check_objects_params check_objects_params = { .expect_count = ARRAY_SIZE(expect_objects), @@ -1283,7 +1278,6 @@ static void test_mouse_info(void) todo_wine check_member( caps, expect_caps, "%#x", dwDevType ); check_member( caps, expect_caps, "%d", dwAxes ); - todo_wine check_member( caps, expect_caps, "%d", dwButtons ); check_member( caps, expect_caps, "%d", dwPOVs ); check_member( caps, expect_caps, "%d", dwFFSamplePeriod ); @@ -1410,7 +1404,6 @@ static void test_mouse_info(void) res = 0; hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON ); ok( hr == DI_OK, "EnumObjects returned %#x\n", hr ); - todo_wine ok( res == 8, "got %u expected %u\n", res, 8 ); hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL ); ok( hr == DI_OK, "EnumObjects returned %#x\n", hr );