And begin some refactoring for `SetActionFormat`.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 139 +++++++++++++++++----------------- dlls/dinput/tests/joystick8.c | 79 ++++--------------- 2 files changed, 84 insertions(+), 134 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index c001d1ef29a..77051eaa620 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -314,31 +314,23 @@ static int id_to_offset( struct dinput_device *impl, int id ) return -1; }
-static DWORD semantic_to_obj_id( struct dinput_device *This, DWORD dwSemantic ) +static BOOL object_matches_semantics( const DIOBJECTDATAFORMAT *object, DWORD semantic, BOOL exact ) { - DWORD type = (0x0000ff00 & dwSemantic) >> 8; - BOOL byofs = (dwSemantic & 0x80000000) != 0; - DWORD value = (dwSemantic & 0x000000ff); - BOOL found = FALSE; - DWORD instance; - int i; + DWORD value = semantic & 0xff, axis = (semantic >> 15) & 3, type;
- for (i = 0; i < This->device_format.dwNumObjs && !found; i++) + switch (semantic & 0x700) { - LPDIOBJECTDATAFORMAT odf = dataformat_to_odf( &This->device_format, i ); - - if (byofs && value != odf->dwOfs) continue; - if (!byofs && value != DIDFT_GETINSTANCE(odf->dwType)) continue; - instance = DIDFT_GETINSTANCE(odf->dwType); - found = TRUE; + case 0x200: type = DIDFT_ABSAXIS; break; + case 0x300: type = DIDFT_RELAXIS; break; + case 0x400: type = DIDFT_BUTTON; break; + case 0x600: type = DIDFT_POV; break; + default: return FALSE; }
- if (!found) return 0; - - if (type & DIDFT_AXIS) type = DIDFT_RELAXIS; - if (type & DIDFT_BUTTON) type = DIDFT_PSHBUTTON; - - return type | (0x0000ff00 & (instance << 8)); + if (!(DIDFT_GETTYPE( object->dwType ) & type)) return FALSE; + if ((semantic & 0xf0000000) == 0x80000000) return object->dwOfs == value; + if (axis && (axis - 1) != DIDFT_GETINSTANCE( object->dwType )) return FALSE; + return !exact || !value || value == DIDFT_GETINSTANCE( object->dwType ) + 1; }
/* @@ -1857,34 +1849,34 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, const WCHAR *username, DWORD flags ) { struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); - BOOL load_success = FALSE, has_actions = FALSE; - DWORD genre, username_len = MAX_PATH; + DIOBJECTDATAFORMAT *object, *object_end; + DIACTIONW *action, *action_end; + DWORD i, username_len = MAX_PATH; WCHAR username_buf[MAX_PATH]; - const DIDATAFORMAT *df; - DWORD devMask; - int i; + BOOL load_success = FALSE; + BOOL *mapped;
FIXME( "iface %p, format %p, username %s, flags %#lx stub!\n", iface, format, debugstr_w(username), flags );
if (!format) return DIERR_INVALIDPARAM; + if (flags != DIDBAM_DEFAULT && flags != DIDBAM_PRESERVE && + flags != DIDBAM_INITIALIZE && flags != DIDBAM_HWDEFAULTS) + return DIERR_INVALIDPARAM; + if (format->dwNumActions * 4 != format->dwDataSize) + return DIERR_INVALIDPARAM;
- switch (GET_DIDEVICE_TYPE( impl->instance.dwDevType )) + action_end = format->rgoAction + format->dwNumActions; + for (action = format->rgoAction; action < action_end; action++) { - case DIDEVTYPE_KEYBOARD: - case DI8DEVTYPE_KEYBOARD: - devMask = DIKEYBOARD_MASK; - df = &c_dfDIKeyboard; - break; - case DIDEVTYPE_MOUSE: - case DI8DEVTYPE_MOUSE: - devMask = DIMOUSE_MASK; - df = &c_dfDIMouse2; - break; - default: - devMask = DIGENRE_ANY; - df = &impl->device_format; - break; + if (!action->dwSemantic) return DIERR_INVALIDPARAM; + if (action->dwFlags & DIA_APPMAPPED) action->dwHow = DIAH_APPREQUESTED; + else if (action->dwFlags & DIA_APPNOMAP) continue; + else + { + action->dwHow = 0; + action->guidInstance = GUID_NULL; + } }
/* Unless asked the contrary by these flags, try to load a previous mapping */ @@ -1897,46 +1889,51 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, }
if (load_success) return DI_OK; + if (!(mapped = calloc( impl->device_format.dwNumObjs, sizeof(*mapped) ))) return DIERR_OUTOFMEMORY;
- for (i = 0; i < format->dwNumActions; i++) + action_end = format->rgoAction + format->dwNumActions; + for (action = format->rgoAction; action < action_end; action++) { - /* Don't touch a user configured action */ - if (format->rgoAction[i].dwHow == DIAH_USERCONFIG) continue; + if (action->dwHow || (action->dwFlags & DIA_APPNOMAP)) continue; /* already mapped */ + if (action->dwSemantic & 0x4000) continue; /* priority 1 */
- genre = format->rgoAction[i].dwSemantic & DIGENRE_ANY; - if (devMask == genre || (devMask == DIGENRE_ANY && genre != DIMOUSE_MASK && genre != DIKEYBOARD_MASK)) + object_end = impl->device_format.rgodf + impl->device_format.dwNumObjs; + for (object = impl->device_format.rgodf; object < object_end; object++) { - DWORD obj_id = semantic_to_obj_id( impl, format->rgoAction[i].dwSemantic ); - DWORD type = DIDFT_GETTYPE( obj_id ); - DWORD inst = DIDFT_GETINSTANCE( obj_id ); - - LPDIOBJECTDATAFORMAT odf; - - if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON; - if (type == DIDFT_RELAXIS) type = DIDFT_AXIS; + if (mapped[object - impl->device_format.rgodf]) continue; + if (!object_matches_semantics( object, action->dwSemantic, TRUE )) continue; + if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; + action->dwObjID = object->dwType; + action->guidInstance = impl->guid; + action->dwHow = DIAH_DEFAULT; + mapped[object - impl->device_format.rgodf] = TRUE; + break; + } + }
- /* Make sure the object exists */ - odf = dataformat_to_odf_by_type( df, inst, type ); + for (action = format->rgoAction; action < action_end; action++) + { + if (action->dwHow || (action->dwFlags & DIA_APPNOMAP)) continue; /* already mapped */ + if (!(action->dwSemantic & 0x4000)) continue; /* priority 2 */
- if (odf != NULL) - { - format->rgoAction[i].dwObjID = obj_id; - format->rgoAction[i].guidInstance = impl->guid; - format->rgoAction[i].dwHow = DIAH_DEFAULT; - has_actions = TRUE; - } - } - else if (!(flags & DIDBAM_PRESERVE)) + object_end = impl->device_format.rgodf + impl->device_format.dwNumObjs; + for (object = impl->device_format.rgodf; object < object_end; object++) { - /* We must clear action data belonging to other devices */ - memset( &format->rgoAction[i].guidInstance, 0, sizeof(GUID) ); - format->rgoAction[i].dwHow = DIAH_UNMAPPED; + if (mapped[object - impl->device_format.rgodf]) continue; + if (!object_matches_semantics( object, action->dwSemantic, FALSE )) continue; + if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; + action->dwObjID = object->dwType; + action->guidInstance = impl->guid; + action->dwHow = DIAH_DEFAULT; + mapped[object - impl->device_format.rgodf] = TRUE; + break; } }
- if (!has_actions) return DI_NOEFFECT; - if (flags & (DIDBAM_DEFAULT|DIDBAM_PRESERVE|DIDBAM_INITIALIZE|DIDBAM_HWDEFAULTS)) - FIXME( "Unimplemented flags %#lx\n", flags ); + for (i = 0; i < impl->device_format.dwNumObjs; ++i) if (mapped[i]) break; + free( mapped ); + + if (i == impl->device_format.dwNumObjs) return DI_NOEFFECT; return DI_OK; }
@@ -2008,7 +2005,7 @@ static HRESULT WINAPI dinput_device_SetActionMap( IDirectInputDevice8W *iface, D if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON; if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
- obj = dataformat_to_odf_by_type( df, inst, type ); + if (!(obj = dataformat_to_odf_by_type( df, inst, type ))) continue;
memcpy( &obj_df[action], obj, df->dwObjSize );
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 70be8f76e1a..5295ee6c169 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -208,16 +208,8 @@ static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect return DIENUM_CONTINUE; }
-struct diaction_todo -{ - BOOL instance; - BOOL objid; - BOOL how; -}; - -#define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b, NULL ) -static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected, - const struct diaction_todo *todos ) +#define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b ) +static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected ) { check_member_( __FILE__, line, *actual, *expected, "%#Ix", uAppData ); check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSemantic ); @@ -226,17 +218,13 @@ static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW check_member_wstr_( __FILE__, line, *actual, *expected, lptszActionName ); else check_member_( __FILE__, line, *actual, *expected, "%p", lptszActionName ); - todo_wine_if( todos->instance ) check_member_guid_( __FILE__, line, *actual, *expected, guidInstance ); - todo_wine_if( todos->objid ) check_member_( __FILE__, line, *actual, *expected, "%#lx", dwObjID ); - todo_wine_if( todos->how ) check_member_( __FILE__, line, *actual, *expected, "%#lx", dwHow ); }
-#define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b, NULL ) -static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected, - const struct diaction_todo *todos ) +#define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b ) +static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected ) { DWORD i; check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSize ); @@ -246,7 +234,7 @@ static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, con for (i = 0; i < min( actual->dwNumActions, expected->dwNumActions ); ++i) { winetest_push_context( "action[%lu]", i ); - check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i, todos ? todos + i : NULL ); + check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i ); winetest_pop_context(); if (expected->dwActionSize != sizeof(DIACTIONW)) break; if (actual->dwActionSize != sizeof(DIACTIONW)) break; @@ -749,29 +737,6 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .lAxisMax = +128, .tszActionMap = L"Action Map Filled", }; - struct diaction_todo actions_todos_1 = {.instance = TRUE, .objid = TRUE, .how = TRUE}; - struct diaction_todo actions_todos_2[ARRAY_SIZE(expect_actions)] = - { - {.instance = TRUE, .objid = TRUE, .how = TRUE}, - {.instance = TRUE, .objid = TRUE, .how = TRUE}, - {0}, - {.instance = TRUE, .objid = TRUE, .how = TRUE}, - {.instance = TRUE, .objid = TRUE, .how = TRUE}, - {.instance = TRUE, .objid = TRUE, .how = TRUE}, - {.instance = TRUE, .objid = TRUE, .how = TRUE}, - {.objid = TRUE}, - }; - struct diaction_todo actions_todos_2_filled[ARRAY_SIZE(expect_actions)] = - { - {.how = TRUE}, - {0}, - {.instance = TRUE, .how = TRUE}, - {.how = TRUE}, - {.instance = TRUE, .how = TRUE}, - {.objid = TRUE, .how = TRUE}, - {.objid = TRUE}, - {.objid = TRUE, .how = TRUE}, - }; DIPROPRANGE prop_range = { .diph = @@ -827,19 +792,15 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e hr = IDirectInputDevice8_BuildActionMap( device, NULL, L"username", DIDBAM_DEFAULT ); ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", 0xdeadbeef ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr ); flags = DIDBAM_HWDEFAULTS | DIDBAM_INITIALIZE; hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", flags ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr ); flags = DIDBAM_HWDEFAULTS | DIDBAM_PRESERVE; hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", flags ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr ); flags = DIDBAM_INITIALIZE | DIDBAM_PRESERVE; hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", flags ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
hr = IDirectInputDevice8_SetActionMap( device, NULL, NULL, DIDSAM_DEFAULT ); @@ -887,13 +848,11 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e memset( actions, 0, sizeof(actions) ); actions[0] = default_actions[0]; hr = IDirectInputDevice8_BuildActionMap( device, &action_format, NULL, DIDBAM_DEFAULT ); - todo_wine ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_1, &actions_todos_1 ); + check_diactionformatw( &action_format, &expect_action_format_1 ); hr = IDirectInputDevice8_SetActionMap( device, &action_format, NULL, DIDSAM_DEFAULT ); - todo_wine ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_1, &actions_todos_1 ); + check_diactionformatw( &action_format, &expect_action_format_1 );
action_format = action_format_1; @@ -901,9 +860,8 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e memset( actions, 0, sizeof(actions) ); actions[0] = default_actions[0]; hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT ); - todo_wine ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_1, &actions_todos_1 ); + check_diactionformatw( &action_format, &expect_action_format_1 );
/* first SetActionMap call for a user always return DI_SETTINGSNOTSAVED */
@@ -911,13 +869,11 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e todo_wine ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr ); hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT ); - todo_wine ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
/* same SetActionMap call returns DI_OK */
hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT ); - todo_wine ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
/* DIDSAM_FORCESAVE always returns DI_SETTINGSNOTSAVED */ @@ -928,7 +884,7 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_FORCESAVE ); todo_wine ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_1, &actions_todos_1 ); + check_diactionformatw( &action_format, &expect_action_format_1 );
/* action format dwDataSize and dwNumActions have to match, actions require a dwSemantic */ @@ -939,11 +895,9 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e actions[0] = default_actions[0]; action_format.dwDataSize = 8; hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr ); action_format.dwNumActions = 2; hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr ); action_format.dwNumActions = 1; action_format.dwDataSize = 4; @@ -954,7 +908,7 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e memcpy( actions, default_actions, sizeof(default_actions) ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT ); ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2, actions_todos_2 ); + check_diactionformatw( &action_format, &expect_action_format_2 );
hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT ); ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr ); @@ -997,16 +951,15 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e action_format.rgoAction = actions; memcpy( actions, filled_actions, sizeof(filled_actions) ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT ); - todo_wine ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2_filled, actions_todos_2_filled ); + check_diactionformatw( &action_format, &expect_action_format_2_filled ); hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT ); ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2_filled, actions_todos_2_filled ); + check_diactionformatw( &action_format, &expect_action_format_2_filled ); hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_FORCESAVE ); todo_wine ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2_filled, actions_todos_2_filled ); + check_diactionformatw( &action_format, &expect_action_format_2_filled );
prop_pointer.diph.dwHow = DIPH_DEVICE; @@ -1060,21 +1013,21 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e memcpy( actions, default_actions, sizeof(default_actions) ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_HWDEFAULTS ); ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2, actions_todos_2 ); + check_diactionformatw( &action_format, &expect_action_format_2 );
action_format = action_format_2; action_format.rgoAction = actions; memcpy( actions, default_actions, sizeof(default_actions) ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_INITIALIZE ); ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2, actions_todos_2 ); + check_diactionformatw( &action_format, &expect_action_format_2 );
action_format = action_format_2; action_format.rgoAction = actions; memcpy( actions, default_actions, sizeof(default_actions) ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE ); ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_2, actions_todos_2 ); + check_diactionformatw( &action_format, &expect_action_format_2 );
hr = IDirectInputDevice8_Acquire( device );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 61 +++++++++++++++--------- dlls/dinput/device_private.h | 3 +- dlls/dinput/joystick_hid.c | 10 ++-- dlls/dinput/keyboard.c | 8 ++-- dlls/dinput/mouse.c | 91 ++++++++++++++++-------------------- 5 files changed, 92 insertions(+), 81 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 77051eaa620..b2487df529b 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -314,23 +314,22 @@ static int id_to_offset( struct dinput_device *impl, int id ) return -1; }
-static BOOL object_matches_semantics( const DIOBJECTDATAFORMAT *object, DWORD semantic, BOOL exact ) +int dinput_device_object_index_from_id( IDirectInputDevice8W *iface, DWORD id ) { - DWORD value = semantic & 0xff, axis = (semantic >> 15) & 3, type; + struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); + const DIDATAFORMAT *format = &impl->device_format; + const DIOBJECTDATAFORMAT *object;
- switch (semantic & 0x700) + if (!format->rgodf) return -1; + + object = format->rgodf + impl->device_format.dwNumObjs; + while (object-- > format->rgodf) { - case 0x200: type = DIDFT_ABSAXIS; break; - case 0x300: type = DIDFT_RELAXIS; break; - case 0x400: type = DIDFT_BUTTON; break; - case 0x600: type = DIDFT_POV; break; - default: return FALSE; + if (!object->dwType) continue; + if ((object->dwType & 0x00ffffff) == (id & 0x00ffffff)) return object - format->rgodf; }
- if (!(DIDFT_GETTYPE( object->dwType ) & type)) return FALSE; - if ((semantic & 0xf0000000) == 0x80000000) return object->dwOfs == value; - if (axis && (axis - 1) != DIDFT_GETINSTANCE( object->dwType )) return FALSE; - return !exact || !value || value == DIDFT_GETINSTANCE( object->dwType ) + 1; + return -1; }
/* @@ -484,12 +483,13 @@ static BOOL set_app_data( struct dinput_device *dev, int offset, UINT_PTR app_da return TRUE; }
-void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD time, DWORD seq ) +void queue_event( IDirectInputDevice8W *iface, int index, DWORD data, DWORD time, DWORD seq ) { static ULONGLONG notify_ms = 0; struct dinput_device *This = impl_from_IDirectInputDevice8W( iface ); - int next_pos, ofs = id_to_offset( This, inst_id ); + const DIOBJECTDATAFORMAT *user_obj = This->user_format.rgodf + index; ULONGLONG time_ms = GetTickCount64(); + int next_pos;
if (time_ms - notify_ms > 1000) { @@ -497,7 +497,7 @@ void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD ti notify_ms = time_ms; }
- if (!This->queue_len || This->overflow || ofs < 0) return; + if (!This->queue_len || This->overflow || !user_obj->dwType) return;
next_pos = (This->queue_head + 1) % This->queue_len; if (next_pos == This->queue_tail) @@ -507,9 +507,9 @@ void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD ti return; }
- TRACE( " queueing %lu at offset %u (queue head %u / size %u)\n", data, ofs, This->queue_head, This->queue_len ); + TRACE( " queueing %lu at offset %lu (queue head %u / size %u)\n", data, user_obj->dwOfs, This->queue_head, This->queue_len );
- This->data_queue[This->queue_head].dwOfs = ofs; + This->data_queue[This->queue_head].dwOfs = user_obj->dwOfs; This->data_queue[This->queue_head].dwData = data; This->data_queue[This->queue_head].dwTimeStamp = time; This->data_queue[This->queue_head].dwSequence = seq; @@ -521,9 +521,9 @@ void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD ti int i; for (i=0; i < This->num_actions; i++) { - if (This->action_map[i].offset == ofs) + if (This->action_map[i].offset == user_obj->dwOfs) { - TRACE( "Offset %d mapped to uAppData %#Ix\n", ofs, This->action_map[i].uAppData ); + TRACE( "Offset %lu mapped to uAppData %#Ix\n", user_obj->dwOfs, This->action_map[i].uAppData ); This->data_queue[This->queue_head].uAppData = This->action_map[i].uAppData; break; } @@ -1845,6 +1845,25 @@ static HRESULT WINAPI dinput_device_WriteEffectToFile( IDirectInputDevice8W *ifa return DI_OK; }
+static BOOL object_matches_semantic( const DIOBJECTDATAFORMAT *object, DWORD semantic, BOOL exact ) +{ + DWORD value = semantic & 0xff, axis = (semantic >> 15) & 3, type; + + switch (semantic & 0x700) + { + case 0x200: type = DIDFT_ABSAXIS; break; + case 0x300: type = DIDFT_RELAXIS; break; + case 0x400: type = DIDFT_BUTTON; break; + case 0x600: type = DIDFT_POV; break; + default: return FALSE; + } + + if (!(DIDFT_GETTYPE( object->dwType ) & type)) return FALSE; + if ((semantic & 0xf0000000) == 0x80000000) return object->dwOfs == value; + if (axis && (axis - 1) != DIDFT_GETINSTANCE( object->dwType )) return FALSE; + return !exact || !value || value == DIDFT_GETINSTANCE( object->dwType ) + 1; +} + static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, DIACTIONFORMATW *format, const WCHAR *username, DWORD flags ) { @@ -1901,7 +1920,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (object = impl->device_format.rgodf; object < object_end; object++) { if (mapped[object - impl->device_format.rgodf]) continue; - if (!object_matches_semantics( object, action->dwSemantic, TRUE )) continue; + if (!object_matches_semantic( object, action->dwSemantic, TRUE )) continue; if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; action->dwObjID = object->dwType; action->guidInstance = impl->guid; @@ -1920,7 +1939,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (object = impl->device_format.rgodf; object < object_end; object++) { if (mapped[object - impl->device_format.rgodf]) continue; - if (!object_matches_semantics( object, action->dwSemantic, FALSE )) continue; + if (!object_matches_semantic( object, action->dwSemantic, FALSE )) continue; if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; action->dwObjID = object->dwType; action->guidInstance = impl->guid; diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index ebe1b49da2f..b044c52ba36 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -130,11 +130,12 @@ extern void dinput_device_internal_addref( struct dinput_device *device ); extern void dinput_device_internal_release( struct dinput_device *device );
extern HRESULT dinput_device_init_device_format( IDirectInputDevice8W *iface ); +extern int dinput_device_object_index_from_id( IDirectInputDevice8W *iface, DWORD id );
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN; extern DWORD get_config_key( HKEY, HKEY, const WCHAR *, WCHAR *, DWORD ) DECLSPEC_HIDDEN; extern BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL *override ) DECLSPEC_HIDDEN; -extern void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD time, DWORD seq ) DECLSPEC_HIDDEN; +extern void queue_event( IDirectInputDevice8W *iface, int index, DWORD data, DWORD time, DWORD seq ) DECLSPEC_HIDDEN;
extern const GUID dinput_pidvid_guid DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 6846410e02c..a91db46c994 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -1109,14 +1109,15 @@ static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_val IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface; struct parse_device_state_params *params = data; BYTE old_value, value; + int index;
if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
value = params->buttons[instance->wUsage - 1]; old_value = params->old_state[instance->dwOfs]; impl->base.device_state[instance->dwOfs] = value; - if (old_value != value) - queue_event( iface, instance->dwType, value, params->time, params->seq ); + if (old_value != value && (index = dinput_device_object_index_from_id( iface, instance->dwType )) >= 0) + queue_event( iface, index, value, params->time, params->seq );
return DIENUM_CONTINUE; } @@ -1186,6 +1187,7 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value char *report_buf = impl->input_report_buf; LONG old_value, value; NTSTATUS status; + int index;
if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
@@ -1198,8 +1200,8 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value
old_value = *(LONG *)(params->old_state + instance->dwOfs); *(LONG *)(impl->base.device_state + instance->dwOfs) = value; - if (old_value != value) - queue_event( iface, instance->dwType, value, params->time, params->seq ); + if (old_value != value && (index = dinput_device_object_index_from_id( iface, instance->dwType )) >= 0) + queue_event( iface, index, value, params->time, params->seq );
return DIENUM_CONTINUE; } diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index c49796cfa2d..73d369b3b5d 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -87,7 +87,7 @@ static void keyboard_handle_event( struct keyboard *impl, DWORD vkey, DWORD scan { BYTE new_diks, subtype = GET_DIDEVICE_SUBTYPE( impl->base.instance.dwDevType ); IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface; - int dik_code; + int dik_code, index;
switch (vkey) { @@ -109,8 +109,10 @@ static void keyboard_handle_event( struct keyboard *impl, DWORD vkey, DWORD scan TRACE( "setting key %02x to %02x\n", dik_code, impl->base.device_state[dik_code] );
EnterCriticalSection( &impl->base.crit ); - queue_event( iface, DIDFT_MAKEINSTANCE( dik_code ) | DIDFT_PSHBUTTON, new_diks, - GetCurrentTime(), impl->base.dinput->evsequence++ ); + + if ((index = dinput_device_object_index_from_id( iface, DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( dik_code ) )) >= 0) + queue_event( iface, index, new_diks, GetCurrentTime(), impl->base.dinput->evsequence++ ); + if (impl->base.hEvent) SetEvent( impl->base.hEvent ); LeaveCriticalSection( &impl->base.crit ); } diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index 502ee797716..8e852907d11 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -37,12 +37,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
-/* Wine mouse driver object instances */ -#define WINE_MOUSE_X_AXIS_INSTANCE 0 -#define WINE_MOUSE_Y_AXIS_INSTANCE 1 -#define WINE_MOUSE_Z_AXIS_INSTANCE 2 -#define WINE_MOUSE_BUTTONS_INSTANCE 3 - static const struct dinput_device_vtbl mouse_vtbl;
typedef enum @@ -160,8 +154,8 @@ void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPA DIMOUSESTATE2 *state = (DIMOUSESTATE2 *)impl->base.device_state; POINT rel, pt; DWORD seq; - int i, wdata = 0; BOOL notify = FALSE; + int i;
static const USHORT mouse_button_flags[] = { @@ -206,15 +200,13 @@ void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPA
if (rel.x) { - queue_event( iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, - pt.x, GetCurrentTime(), seq ); + queue_event( iface, 0, pt.x, GetCurrentTime(), seq ); notify = TRUE; }
if (rel.y) { - queue_event( iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, - pt.y, GetCurrentTime(), seq ); + queue_event( iface, 1, pt.y, GetCurrentTime(), seq ); notify = TRUE; }
@@ -227,9 +219,8 @@ void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPA
if (ri->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { - state->lZ += (wdata = (SHORT)ri->data.mouse.usButtonData); - queue_event( iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS, - wdata, GetCurrentTime(), seq ); + state->lZ += (SHORT)ri->data.mouse.usButtonData; + queue_event( iface, 2, (SHORT)ri->data.mouse.usButtonData, GetCurrentTime(), seq ); notify = TRUE; }
@@ -238,8 +229,7 @@ void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPA if (ri->data.mouse.usButtonFlags & mouse_button_flags[i]) { state->rgbButtons[i / 2] = 0x80 - (i % 2) * 0x80; - queue_event( iface, DIDFT_MAKEINSTANCE( WINE_MOUSE_BUTTONS_INSTANCE + (i / 2) ) | DIDFT_PSHBUTTON, - state->rgbButtons[i / 2], GetCurrentTime(), seq ); + queue_event( iface, 3 + (i / 2), state->rgbButtons[i / 2], GetCurrentTime(), seq ); notify = TRUE; } } @@ -257,12 +247,14 @@ int dinput_mouse_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam; struct mouse *impl = impl_from_IDirectInputDevice8W( iface ); DIMOUSESTATE2 *state = (DIMOUSESTATE2 *)impl->base.device_state; - int wdata = 0, inst_id = -1, ret = 0; BOOL notify = FALSE; + int ret = 0; + DWORD seq;
TRACE( "iface %p, msg %#Ix, x %+ld, y %+ld\n", iface, wparam, hook->pt.x, hook->pt.y );
EnterCriticalSection( &impl->base.crit ); + seq = impl->base.dinput->evsequence++;
switch(wparam) { case WM_MOUSEMOVE: @@ -282,19 +274,13 @@ int dinput_mouse_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam
if (pt.x) { - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS; - wdata = pt1.x; + queue_event( iface, 0, pt1.x, GetCurrentTime(), seq ); + notify = TRUE; } if (pt.y) { - /* Already have X, need to queue it */ - if (inst_id != -1) - { - queue_event( iface, inst_id, wdata, GetCurrentTime(), impl->base.dinput->evsequence ); - notify = TRUE; - } - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS; - wdata = pt1.y; + queue_event( iface, 1, pt1.y, GetCurrentTime(), seq ); + notify = TRUE; }
if (pt.x || pt.y) @@ -306,53 +292,54 @@ int dinput_mouse_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam break; } case WM_MOUSEWHEEL: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS; - state->lZ += wdata = (short)HIWORD( hook->mouseData ); + state->lZ += (short)HIWORD( hook->mouseData ); + queue_event( iface, 2, state->lZ, GetCurrentTime(), seq ); /* FarCry crashes if it gets a mouse wheel message */ /* FIXME: should probably filter out other messages too */ ret = impl->clipped; break; case WM_LBUTTONDOWN: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON; - state->rgbButtons[0] = wdata = 0x80; + state->rgbButtons[0] = 0x80; + queue_event( iface, 3, 0x80, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_LBUTTONUP: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON; - state->rgbButtons[0] = wdata = 0x00; + state->rgbButtons[0] = 0x00; + queue_event( iface, 3, 0x00, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_RBUTTONDOWN: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON; - state->rgbButtons[1] = wdata = 0x80; + state->rgbButtons[1] = 0x80; + queue_event( iface, 4, 0x80, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_RBUTTONUP: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON; - state->rgbButtons[1] = wdata = 0x00; + state->rgbButtons[1] = 0x00; + queue_event( iface, 4, 0x00, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_MBUTTONDOWN: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON; - state->rgbButtons[2] = wdata = 0x80; + state->rgbButtons[2] = 0x80; + queue_event( iface, 5, 0x80, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_MBUTTONUP: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON; - state->rgbButtons[2] = wdata = 0x00; + state->rgbButtons[2] = 0x00; + queue_event( iface, 5, 0x00, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_XBUTTONDOWN: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON; - state->rgbButtons[2 + HIWORD( hook->mouseData )] = wdata = 0x80; + state->rgbButtons[2 + HIWORD( hook->mouseData )] = 0x80; + queue_event( iface, 5 + HIWORD(hook->mouseData), 0x80, GetCurrentTime(), seq ); + notify = TRUE; break; case WM_XBUTTONUP: - inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON; - state->rgbButtons[2 + HIWORD( hook->mouseData )] = wdata = 0x00; + state->rgbButtons[2 + HIWORD( hook->mouseData )] = 0x00; + queue_event( iface, 5 + HIWORD(hook->mouseData), 0x00, GetCurrentTime(), seq ); + notify = TRUE; break; }
- - if (inst_id != -1) - { - queue_event( iface, inst_id, wdata, GetCurrentTime(), impl->base.dinput->evsequence++ ); - notify = TRUE; - } - TRACE( "buttons %02x %02x %02x %02x %02x, x %+ld, y %+ld, w %+ld\n", state->rgbButtons[0], state->rgbButtons[1], state->rgbButtons[2], state->rgbButtons[3], state->rgbButtons[4], state->lX, state->lY, state->lZ );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 51 +++++++++++++------ dlls/dinput/device_private.h | 8 ++- dlls/dinput/joystick_hid.c | 96 ++++++++++++++---------------------- dlls/dinput/keyboard.c | 18 +++---- dlls/dinput/mouse.c | 15 +++--- 5 files changed, 97 insertions(+), 91 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index b2487df529b..7fa2a89cf35 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -792,8 +792,22 @@ static ULONG WINAPI dinput_device_AddRef( IDirectInputDevice8W *iface ) return ref; }
-static HRESULT WINAPI dinput_device_EnumObjects( IDirectInputDevice8W *iface, - LPDIENUMDEVICEOBJECTSCALLBACKW callback, +struct enum_objects_params +{ + LPDIENUMDEVICEOBJECTSCALLBACKW callback; + void *context; +}; + +static BOOL enum_objects_callback( struct dinput_device *impl, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + struct enum_objects_params *params = data; + if (instance->wUsagePage == HID_USAGE_PAGE_PID && !(instance->dwType & DIDFT_NODATA)) + return DIENUM_CONTINUE; + return params->callback( instance, params->context ); +} + +static HRESULT WINAPI dinput_device_EnumObjects( IDirectInputDevice8W *iface, LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context, DWORD flags ) { static const DIPROPHEADER filter = @@ -802,6 +816,7 @@ static HRESULT WINAPI dinput_device_EnumObjects( IDirectInputDevice8W *iface, .dwHeaderSize = sizeof(filter), .dwHow = DIPH_DEVICE, }; + struct enum_objects_params params = {.callback = callback, .context = context}; struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); HRESULT hr;
@@ -813,25 +828,25 @@ static HRESULT WINAPI dinput_device_EnumObjects( IDirectInputDevice8W *iface,
if (flags == DIDFT_ALL || (flags & DIDFT_AXIS)) { - hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, callback, context ); + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, enum_objects_callback, ¶ms ); if (FAILED(hr)) return hr; if (hr != DIENUM_CONTINUE) return DI_OK; } if (flags == DIDFT_ALL || (flags & DIDFT_POV)) { - hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_POV, callback, context ); + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_POV, enum_objects_callback, ¶ms ); if (FAILED(hr)) return hr; if (hr != DIENUM_CONTINUE) return DI_OK; } if (flags == DIDFT_ALL || (flags & DIDFT_BUTTON)) { - hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_BUTTON, callback, context ); + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_BUTTON, enum_objects_callback, ¶ms ); if (FAILED(hr)) return hr; if (hr != DIENUM_CONTINUE) return DI_OK; } if (flags == DIDFT_ALL || (flags & (DIDFT_NODATA | DIDFT_COLLECTION))) { - hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_NODATA, callback, context ); + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_NODATA, enum_objects_callback, ¶ms ); if (FAILED(hr)) return hr; if (hr != DIENUM_CONTINUE) return DI_OK; } @@ -1045,9 +1060,10 @@ static HRESULT check_property( struct dinput_device *impl, const GUID *guid, con return DI_OK; }
-static BOOL CALLBACK find_object( const DIDEVICEOBJECTINSTANCEW *instance, void *context ) +static BOOL find_object( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - *(DIDEVICEOBJECTINSTANCEW *)context = *instance; + *(DIDEVICEOBJECTINSTANCEW *)data = *instance; return DIENUM_STOP; }
@@ -1058,7 +1074,8 @@ struct get_object_property_params DWORD property; };
-static BOOL CALLBACK get_object_property( const DIDEVICEOBJECTINSTANCEW *instance, void *context ) +static BOOL get_object_property( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { static const struct object_properties default_properties = { @@ -1066,7 +1083,7 @@ static BOOL CALLBACK get_object_property( const DIDEVICEOBJECTINSTANCEW *instanc .range_max = DIPROPRANGE_NOMAX, .granularity = 1, }; - struct get_object_property_params *params = context; + struct get_object_property_params *params = data; struct dinput_device *impl = impl_from_IDirectInputDevice8W( params->iface ); const struct object_properties *properties = NULL;
@@ -1235,9 +1252,10 @@ struct set_object_property_params DWORD property; };
-static BOOL CALLBACK set_object_property( const DIDEVICEOBJECTINSTANCEW *instance, void *context ) +static BOOL set_object_property( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - struct set_object_property_params *params = context; + struct set_object_property_params *params = data; struct dinput_device *impl = impl_from_IDirectInputDevice8W( params->iface ); struct object_properties *properties = NULL;
@@ -1276,9 +1294,9 @@ static BOOL CALLBACK set_object_property( const DIDEVICEOBJECTINSTANCEW *instanc return DIENUM_STOP; }
-static BOOL CALLBACK reset_object_value( const DIDEVICEOBJECTINSTANCEW *instance, void *context ) +static BOOL reset_object_value( struct dinput_device *impl, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *context ) { - struct dinput_device *impl = context; struct object_properties *properties; LONG tmp = -1;
@@ -1445,7 +1463,8 @@ static void dinput_device_set_username( struct dinput_device *impl, const DIPROP lstrcpynW( device_player->username, value->wsz, ARRAY_SIZE(device_player->username) ); }
-static BOOL CALLBACK get_object_info( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL get_object_info( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { DIDEVICEOBJECTINSTANCEW *dest = data; DWORD size = dest->dwSize; @@ -2194,7 +2213,7 @@ static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, }
if (impl->object_properties && (instance->dwType & (DIDFT_AXIS | DIDFT_POV))) - reset_object_value( instance, impl ); + reset_object_value( impl, format->dwNumObjs, NULL, instance, NULL );
format->dwNumObjs++; return DIENUM_CONTINUE; diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index b044c52ba36..65453f6313d 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -34,6 +34,12 @@ typedef struct UINT_PTR uAppData; } ActionMap;
+struct dinput_device; +struct hid_value_caps; + +typedef BOOL (*enum_object_callback)( struct dinput_device *impl, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ); + struct dinput_device_vtbl { void (*destroy)( IDirectInputDevice8W *iface ); @@ -42,7 +48,7 @@ struct dinput_device_vtbl HRESULT (*acquire)( IDirectInputDevice8W *iface ); HRESULT (*unacquire)( IDirectInputDevice8W *iface ); HRESULT (*enum_objects)( IDirectInputDevice8W *iface, const DIPROPHEADER *filter, DWORD flags, - LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context ); + enum_object_callback callback, void *context ); HRESULT (*get_property)( IDirectInputDevice8W *iface, DWORD property, DIPROPHEADER *header, const DIDEVICEOBJECTINSTANCEW *instance ); HRESULT (*get_effect_info)( IDirectInputDevice8W *iface, DIEFFECTINFOW *info, const GUID *guid ); diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index a91db46c994..e8a554142f4 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -478,11 +478,8 @@ static HRESULT find_next_effect_id( struct hid_joystick *impl, ULONG *index, USA return DI_OK; }
-typedef BOOL (*enum_object_callback)( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ); - static BOOL enum_object( struct hid_joystick *impl, const DIPROPHEADER *filter, DWORD flags, - enum_object_callback callback, struct hid_value_caps *caps, + enum_object_callback callback, UINT index, struct hid_value_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data ) { if (flags != DIDFT_ALL && !(flags & DIDFT_GETTYPE( instance->dwType ))) return DIENUM_CONTINUE; @@ -490,17 +487,17 @@ static BOOL enum_object( struct hid_joystick *impl, const DIPROPHEADER *filter, switch (filter->dwHow) { case DIPH_DEVICE: - return callback( impl, caps, instance, data ); + return callback( &impl->base, index, caps, instance, data ); case DIPH_BYOFFSET: if (filter->dwObj != instance->dwOfs) return DIENUM_CONTINUE; - return callback( impl, caps, instance, data ); + return callback( &impl->base, index, caps, instance, data ); case DIPH_BYID: if ((filter->dwObj & 0x00ffffff) != (instance->dwType & 0x00ffffff)) return DIENUM_CONTINUE; - return callback( impl, caps, instance, data ); + return callback( &impl->base, index, caps, instance, data ); case DIPH_BYUSAGE: if (HIWORD( filter->dwObj ) != instance->wUsagePage) return DIENUM_CONTINUE; if (LOWORD( filter->dwObj ) != instance->wUsage) return DIENUM_CONTINUE; - return callback( impl, caps, instance, data ); + return callback( &impl->base, index, caps, instance, data ); default: FIXME( "unimplemented filter dwHow %#lx dwObj %#lx\n", filter->dwHow, filter->dwObj ); break; @@ -616,7 +613,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, if ((tmp = object_usage_to_string( &instance ))) lstrcpynW( instance.tszName, tmp, MAX_PATH ); else swprintf( instance.tszName, MAX_PATH, L"Unknown %u", DIDFT_GETINSTANCE( instance.dwType ) ); check_pid_effect_axis_caps( impl, &instance ); - ret = enum_object( impl, filter, flags, callback, caps, &instance, data ); + ret = enum_object( impl, filter, flags, callback, object, caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; value_ofs += sizeof(LONG); object++; @@ -651,7 +648,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.dwDimension = caps->units; instance.wExponent = caps->units_exp; swprintf( instance.tszName, MAX_PATH, L"Button %u", DIDFT_GETINSTANCE( instance.dwType ) ); - ret = enum_object( impl, filter, flags, callback, caps, &instance, data ); + ret = enum_object( impl, filter, flags, callback, object, caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; button_ofs++; object++; @@ -690,7 +687,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.wExponent = caps->units_exp; if ((tmp = object_usage_to_string( &instance ))) lstrcpynW( instance.tszName, tmp, MAX_PATH ); else swprintf( instance.tszName, MAX_PATH, L"Unknown %u", DIDFT_GETINSTANCE( instance.dwType ) ); - ret = enum_object( impl, filter, flags, callback, nary, &instance, data ); + ret = enum_object( impl, filter, flags, callback, -1, nary, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; button_ofs++; } @@ -712,7 +709,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.wExponent = caps->units_exp; if ((tmp = object_usage_to_string( &instance ))) lstrcpynW( instance.tszName, tmp, MAX_PATH ); else swprintf( instance.tszName, MAX_PATH, L"Unknown %u", DIDFT_GETINSTANCE( instance.dwType ) ); - ret = enum_object( impl, filter, flags, callback, caps, &instance, data ); + ret = enum_object( impl, filter, flags, callback, -1, caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret;
if (caps->flags & HID_VALUE_CAPS_IS_BUTTON) button_ofs++; @@ -739,7 +736,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, len = swprintf( instance.tszName, MAX_PATH, L"Collection %u - ", DIDFT_GETINSTANCE( instance.dwType ) ); if ((tmp = object_usage_to_string( &instance ))) lstrcpynW( instance.tszName + len, tmp, MAX_PATH - len ); else swprintf( instance.tszName + len, MAX_PATH - len, L"Unknown %u", DIDFT_GETINSTANCE( instance.dwType ) ); - ret = enum_object( impl, filter, flags, callback, NULL, &instance, data ); + ret = enum_object( impl, filter, flags, callback, -1, NULL, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; } } @@ -1103,21 +1100,19 @@ struct parse_device_state_params DWORD seq; };
-static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL check_device_state_button( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface; + IDirectInputDevice8W *iface = &device->IDirectInputDevice8W_iface; struct parse_device_state_params *params = data; BYTE old_value, value; - int index;
- if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE; + if (instance->wReportId != device->device_state_report_id) return DIENUM_CONTINUE;
value = params->buttons[instance->wUsage - 1]; old_value = params->old_state[instance->dwOfs]; - impl->base.device_state[instance->dwOfs] = value; - if (old_value != value && (index = dinput_device_object_index_from_id( iface, instance->dwType )) >= 0) - queue_event( iface, index, value, params->time, params->seq ); + device->device_state[instance->dwOfs] = value; + if (old_value != value) queue_event( iface, index, value, params->time, params->seq );
return DIENUM_CONTINUE; } @@ -1177,9 +1172,10 @@ static LONG scale_axis_value( ULONG value, struct object_properties *properties return phy_min + MulDiv( tmp - log_min, phy_max - phy_min, log_max - log_min ); }
-static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL read_device_state_value( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { + struct hid_joystick *impl = CONTAINING_RECORD( device, struct hid_joystick, base ); struct object_properties *properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG); IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface; ULONG logical_value, report_len = impl->caps.InputReportByteLength; @@ -1187,7 +1183,6 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value char *report_buf = impl->input_report_buf; LONG old_value, value; NTSTATUS status; - int index;
if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
@@ -1200,8 +1195,7 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value
old_value = *(LONG *)(params->old_state + instance->dwOfs); *(LONG *)(impl->base.device_state + instance->dwOfs) = value; - if (old_value != value && (index = dinput_device_object_index_from_id( iface, instance->dwType )) >= 0) - queue_event( iface, index, value, params->time, params->seq ); + if (old_value != value) queue_event( iface, index, value, params->time, params->seq );
return DIENUM_CONTINUE; } @@ -1331,27 +1325,11 @@ static HRESULT hid_joystick_read( IDirectInputDevice8W *iface ) return hr; }
-struct enum_objects_params -{ - LPDIENUMDEVICEOBJECTSCALLBACKW callback; - void *context; -}; - -static BOOL enum_objects_callback( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) -{ - struct enum_objects_params *params = data; - if (instance->wUsagePage == HID_USAGE_PAGE_PID && !(instance->dwType & DIDFT_NODATA)) - return DIENUM_CONTINUE; - return params->callback( instance, params->context ); -} - static HRESULT hid_joystick_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *filter, - DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context ) + DWORD flags, enum_object_callback callback, void *context ) { - struct enum_objects_params params = {.callback = callback, .context = context}; struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); - return enum_objects( impl, filter, flags, enum_objects_callback, ¶ms ); + return enum_objects( impl, filter, flags, callback, context ); }
static const struct dinput_device_vtbl hid_joystick_vtbl = @@ -1664,10 +1642,10 @@ HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *in return DI_OK; }
-static BOOL init_object_properties( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL init_object_properties( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - struct object_properties *properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG); + struct object_properties *properties = device->object_properties + instance->dwOfs / sizeof(LONG); LONG tmp;
properties->bit_size = caps->bit_size; @@ -1689,9 +1667,10 @@ static BOOL init_object_properties( struct hid_joystick *impl, struct hid_value_ return DIENUM_CONTINUE; }
-static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL init_pid_reports( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { + struct hid_joystick *impl = CONTAINING_RECORD( device, struct hid_joystick, base ); struct pid_set_constant_force *set_constant_force = &impl->pid_set_constant_force; struct pid_set_ramp_force *set_ramp_force = &impl->pid_set_ramp_force; struct pid_control_report *device_control = &impl->pid_device_control; @@ -1763,9 +1742,10 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * return DIENUM_CONTINUE; }
-static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL init_pid_caps( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { + struct hid_joystick *impl = CONTAINING_RECORD( device, struct hid_joystick, base ); struct pid_set_constant_force *set_constant_force = &impl->pid_set_constant_force; struct pid_set_ramp_force *set_ramp_force = &impl->pid_set_ramp_force; struct pid_control_report *device_control = &impl->pid_device_control; @@ -2257,17 +2237,17 @@ static HRESULT WINAPI hid_joystick_effect_GetEffectGuid( IDirectInputEffect *ifa return DI_OK; }
-static BOOL get_parameters_object_id( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL get_parameters_object_id( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { *(DWORD *)data = instance->dwType; return DIENUM_STOP; }
-static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL get_parameters_object_ofs( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - DIDATAFORMAT *device_format = &impl->base.device_format, *user_format = &impl->base.user_format; + DIDATAFORMAT *device_format = &device->device_format, *user_format = &device->user_format; DIOBJECTDATAFORMAT *device_obj, *user_obj;
if (!user_format->rgodf) return DIENUM_CONTINUE; @@ -2518,8 +2498,8 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa return DI_OK; }
-static BOOL set_parameters_object( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL set_parameters_object( struct dinput_device *device, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { DWORD usages = MAKELONG( instance->wUsage, instance->wUsagePage ); *(DWORD *)data = usages; diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index 73d369b3b5d..0dfc909585a 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -228,28 +228,28 @@ static HRESULT keyboard_unacquire( IDirectInputDevice8W *iface ) return DI_OK; }
-static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL try_enum_object( struct dinput_device *impl, const DIPROPHEADER *filter, DWORD flags, enum_object_callback callback, + UINT index, 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 ); + return callback( impl, index, NULL, instance, data ); case DIPH_BYOFFSET: if (filter->dwObj != instance->dwOfs) return DIENUM_CONTINUE; - return callback( instance, data ); + return callback( impl, index, NULL, instance, data ); case DIPH_BYID: if ((filter->dwObj & 0x00ffffff) != (instance->dwType & 0x00ffffff)) return DIENUM_CONTINUE; - return callback( instance, data ); + return callback( impl, index, NULL, instance, data ); }
return DIENUM_CONTINUE; }
static HRESULT keyboard_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *filter, - DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context ) + DWORD flags, enum_object_callback callback, void *context ) { struct keyboard *impl = impl_from_IDirectInputDevice8W( iface ); BYTE subtype = GET_DIDEVICE_SUBTYPE( impl->base.instance.dwDevType ); @@ -260,16 +260,16 @@ static HRESULT keyboard_enum_objects( IDirectInputDevice8W *iface, const DIPROPH .dwOfs = DIK_ESCAPE, .dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( DIK_ESCAPE ), }; - DWORD i, dik; + DWORD index, i, dik; BOOL ret;
- for (i = 0; i < 512; ++i) + for (i = 0, index = 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 ); + ret = try_enum_object( &impl->base, filter, flags, callback, index++, &instance, context ); if (ret != DIENUM_CONTINUE) return DIENUM_STOP; }
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index 8e852907d11..9b1bf74b8d5 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -456,29 +456,30 @@ static HRESULT mouse_unacquire( IDirectInputDevice8W *iface ) return DI_OK; }
-static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL try_enum_object( struct dinput_device *impl, const DIPROPHEADER *filter, DWORD flags, enum_object_callback callback, + UINT index, 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 ); + return callback( impl, index, NULL, instance, data ); case DIPH_BYOFFSET: if (filter->dwObj != instance->dwOfs) return DIENUM_CONTINUE; - return callback( instance, data ); + return callback( impl, index, NULL, instance, data ); case DIPH_BYID: if ((filter->dwObj & 0x00ffffff) != (instance->dwType & 0x00ffffff)) return DIENUM_CONTINUE; - return callback( instance, data ); + return callback( impl, index, NULL, instance, data ); }
return DIENUM_CONTINUE; }
static HRESULT mouse_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *filter, - DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context ) + DWORD flags, enum_object_callback callback, void *context ) { + struct mouse *impl = impl_from_IDirectInputDevice8W( iface ); DIDEVICEOBJECTINSTANCEW instances[] = { { @@ -546,7 +547,7 @@ static HRESULT mouse_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEAD
for (i = 0; i < ARRAY_SIZE(instances); ++i) { - ret = try_enum_object( filter, flags, callback, instances + i, context ); + ret = try_enum_object( &impl->base, filter, flags, callback, i, instances + i, context ); if (ret != DIENUM_CONTINUE) return DIENUM_STOP; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 50 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 23 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 7fa2a89cf35..df19f615a55 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -2183,35 +2183,39 @@ static const GUID *object_instance_guid( const DIDEVICEOBJECTINSTANCEW *instance return &GUID_Unknown; }
-static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL CALLBACK enum_objects_count( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { struct dinput_device *impl = impl_from_IDirectInputDevice8W( data ); DIDATAFORMAT *format = &impl->device_format; - DIOBJECTDATAFORMAT *obj_format;
- if (!format->rgodf) + format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) ); + if (instance->dwType & DIDFT_BUTTON) impl->caps.dwButtons++; + if (instance->dwType & DIDFT_AXIS) impl->caps.dwAxes++; + if (instance->dwType & DIDFT_POV) impl->caps.dwPOVs++; + if (instance->dwType & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV)) { - format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) ); - if (instance->dwType & DIDFT_BUTTON) impl->caps.dwButtons++; - if (instance->dwType & DIDFT_AXIS) impl->caps.dwAxes++; - if (instance->dwType & DIDFT_POV) impl->caps.dwPOVs++; - if (instance->dwType & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV)) - { - if (!impl->device_state_report_id) - impl->device_state_report_id = instance->wReportId; - else if (impl->device_state_report_id != instance->wReportId) - FIXME( "multiple device state reports found!\n" ); - } - } - else - { - obj_format = format->rgodf + format->dwNumObjs; - obj_format->pguid = object_instance_guid( instance ); - obj_format->dwOfs = instance->dwOfs; - obj_format->dwType = instance->dwType; - obj_format->dwFlags = instance->dwFlags; + if (!impl->device_state_report_id) + impl->device_state_report_id = instance->wReportId; + else if (impl->device_state_report_id != instance->wReportId) + FIXME( "multiple device state reports found!\n" ); }
+ format->dwNumObjs++; + return DIENUM_CONTINUE; +} + +static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + struct dinput_device *impl = impl_from_IDirectInputDevice8W( data ); + DIDATAFORMAT *format = &impl->device_format; + DIOBJECTDATAFORMAT *object_format; + + object_format = format->rgodf + format->dwNumObjs; + object_format->pguid = object_instance_guid( instance ); + object_format->dwOfs = instance->dwOfs; + object_format->dwType = instance->dwType; + object_format->dwFlags = instance->dwFlags; + if (impl->object_properties && (instance->dwType & (DIDFT_AXIS | DIDFT_POV))) reset_object_value( impl, format->dwNumObjs, NULL, instance, NULL );
@@ -2225,7 +2229,7 @@ HRESULT dinput_device_init_device_format( IDirectInputDevice8W *iface ) DIDATAFORMAT *format = &impl->device_format; ULONG i, size;
- IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL ); + IDirectInputDevice8_EnumObjects( iface, enum_objects_count, iface, DIDFT_ALL ); if (format->dwDataSize > DEVICE_STATE_MAX_SIZE) { FIXME( "unable to create device, state is too large\n" );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index df19f615a55..407e4f52a38 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -2183,11 +2183,15 @@ static const GUID *object_instance_guid( const DIDEVICEOBJECTINSTANCEW *instance return &GUID_Unknown; }
-static BOOL CALLBACK enum_objects_count( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL enum_objects_count( struct dinput_device *impl, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - struct dinput_device *impl = impl_from_IDirectInputDevice8W( data ); DIDATAFORMAT *format = &impl->device_format;
+ if (index == -1) return DIENUM_STOP; + format->dwNumObjs++; + if (instance->wUsagePage == HID_USAGE_PAGE_PID) return DIENUM_CONTINUE; + format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) ); if (instance->dwType & DIDFT_BUTTON) impl->caps.dwButtons++; if (instance->dwType & DIDFT_AXIS) impl->caps.dwAxes++; @@ -2200,36 +2204,46 @@ static BOOL CALLBACK enum_objects_count( const DIDEVICEOBJECTINSTANCEW *instance FIXME( "multiple device state reports found!\n" ); }
- format->dwNumObjs++; return DIENUM_CONTINUE; }
-static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +static BOOL enum_objects_init( struct dinput_device *impl, UINT index, struct hid_value_caps *caps, + const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - struct dinput_device *impl = impl_from_IDirectInputDevice8W( data ); DIDATAFORMAT *format = &impl->device_format; DIOBJECTDATAFORMAT *object_format;
- object_format = format->rgodf + format->dwNumObjs; + if (index == -1) return DIENUM_STOP; + if (instance->wUsagePage == HID_USAGE_PAGE_PID) return DIENUM_CONTINUE; + + object_format = format->rgodf + index; object_format->pguid = object_instance_guid( instance ); object_format->dwOfs = instance->dwOfs; object_format->dwType = instance->dwType; object_format->dwFlags = instance->dwFlags;
if (impl->object_properties && (instance->dwType & (DIDFT_AXIS | DIDFT_POV))) - reset_object_value( impl, format->dwNumObjs, NULL, instance, NULL ); + reset_object_value( impl, index, caps, instance, NULL );
- format->dwNumObjs++; return DIENUM_CONTINUE; }
HRESULT dinput_device_init_device_format( IDirectInputDevice8W *iface ) { + static const DIPROPHEADER filter = + { + .dwSize = sizeof(filter), + .dwHeaderSize = sizeof(filter), + .dwHow = DIPH_DEVICE, + }; struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); DIDATAFORMAT *format = &impl->device_format; ULONG i, size; + HRESULT hr; + + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_ALL, enum_objects_count, NULL ); + if (FAILED(hr)) return hr;
- IDirectInputDevice8_EnumObjects( iface, enum_objects_count, iface, DIDFT_ALL ); if (format->dwDataSize > DEVICE_STATE_MAX_SIZE) { FIXME( "unable to create device, state is too large\n" ); @@ -2242,8 +2256,15 @@ HRESULT dinput_device_init_device_format( IDirectInputDevice8W *iface ) format->dwSize = sizeof(*format); format->dwObjSize = sizeof(*format->rgodf); format->dwFlags = DIDF_ABSAXIS; - format->dwNumObjs = 0; - IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL ); + + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, enum_objects_init, NULL ); + if (FAILED(hr)) return hr; + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_POV, enum_objects_init, NULL ); + if (FAILED(hr)) return hr; + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_BUTTON, enum_objects_init, NULL ); + if (FAILED(hr)) return hr; + hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_NODATA, enum_objects_init, NULL ); + if (FAILED(hr)) return hr;
if (TRACE_ON( dinput )) {