Commit d62e2268 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

dinput: Rewrite IDirectInput8_EnumDevicesBySemantics.

Simplifying and fixing it.
parent cb987646
......@@ -1785,7 +1785,7 @@ static HRESULT WINAPI dinput_device_WriteEffectToFile( IDirectInputDevice8W *ifa
return DI_OK;
}
static BOOL object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object,
BOOL device_object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object,
DWORD semantic, BOOL exact )
{
DWORD value = semantic & 0xff, axis = (semantic >> 15) & 3, type;
......@@ -1885,7 +1885,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_semantic( &impl->instance, object, action->dwSemantic, TRUE )) continue;
if (!device_object_matches_semantic( &impl->instance, object, action->dwSemantic, TRUE )) continue;
if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue;
action->dwObjID = object->dwType;
action->guidInstance = impl->guid;
......@@ -1904,7 +1904,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_semantic( &impl->instance, object, action->dwSemantic, FALSE )) continue;
if (!device_object_matches_semantic( &impl->instance, object, action->dwSemantic, FALSE )) continue;
if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue;
action->dwObjID = object->dwType;
action->guidInstance = impl->guid;
......
......@@ -128,6 +128,8 @@ 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 device_object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object,
DWORD semantic, BOOL exact );
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
extern DWORD get_config_key( HKEY, HKEY, const WCHAR *, WCHAR *, DWORD ) DECLSPEC_HIDDEN;
......
......@@ -45,19 +45,6 @@ static inline struct dinput *impl_from_IDirectInput8W( IDirectInput8W *iface )
return CONTAINING_RECORD( iface, struct dinput, IDirectInput8W_iface );
}
static DWORD diactionformat_priorityW( DIACTIONFORMATW *action_format, DWORD genre )
{
int i;
DWORD priorityFlags = 0;
/* If there's at least one action for the device it's priority 1 */
for (i = 0; i < action_format->dwNumActions; i++)
if ((action_format->rgoAction[i].dwSemantic & genre) == genre)
priorityFlags |= DIEDBS_MAPPEDPRI1;
return priorityFlags;
}
#if defined __i386__ && defined _MSC_VER
__declspec(naked) BOOL enum_callback_wrapper(void *callback, const void *instance, void *ref)
{
......@@ -438,65 +425,82 @@ static HRESULT WINAPI dinput8_FindDevice( IDirectInput8W *iface, const GUID *gui
return IDirectInput7_FindDevice( &impl->IDirectInput7W_iface, guid, name, instance_guid );
}
static BOOL should_enumerate_device( const WCHAR *username, DWORD flags, struct list *device_players, const GUID *guid )
struct enum_device_by_semantics_params
{
BOOL should_enumerate = TRUE;
struct DevicePlayer *device_player;
IDirectInput8W *iface;
const WCHAR *username;
DWORD flags;
/* Check if user owns impl device */
if (flags & DIEDBSFL_THISUSER && username && *username)
IDirectInputDevice8W *devices[128];
DWORD device_count;
};
static BOOL CALLBACK enum_device_by_semantics( const DIDEVICEINSTANCEW *instance, void *context )
{
struct enum_device_by_semantics_params *params = context;
DIDEVCAPS caps = {.dwSize = sizeof(caps)};
DIPROPSTRING prop_username =
{
should_enumerate = FALSE;
LIST_FOR_EACH_ENTRY( device_player, device_players, struct DevicePlayer, entry )
.diph =
{
if (IsEqualGUID( &device_player->instance_guid, guid ))
{
if (*device_player->username && !wcscmp( username, device_player->username ))
return TRUE; /* Device username matches */
break;
}
}
}
.dwSize = sizeof(DIPROPSTRING),
.dwHeaderSize = sizeof(DIPROPHEADER),
.dwHow = DIPH_DEVICE,
},
};
IDirectInputDevice8W *device;
BOOL ret = DIENUM_CONTINUE;
HRESULT hr;
/* Check if impl device is not owned by anyone */
if (flags & DIEDBSFL_AVAILABLEDEVICES)
if (params->device_count >= ARRAY_SIZE(params->devices)) return DIENUM_STOP;
if (FAILED(hr = IDirectInput8_CreateDevice( params->iface, &instance->guidInstance, &device, NULL )))
{
BOOL found = FALSE;
should_enumerate = FALSE;
LIST_FOR_EACH_ENTRY( device_player, device_players, struct DevicePlayer, entry )
{
if (IsEqualGUID( &device_player->instance_guid, guid ))
{
if (*device_player->username) found = TRUE;
break;
}
}
if (!found) return TRUE; /* Device does not have a username */
WARN( "Failed to create device, hr %#lx\n", hr );
return DIENUM_CONTINUE;
}
return should_enumerate;
if (FAILED(hr = IDirectInputDevice8_GetCapabilities( device, &caps )))
WARN( "Failed to get device capabilities, hr %#lx\n", hr );
if ((params->flags & DIEDBSFL_FORCEFEEDBACK) && !caps.dwFFDriverVersion) goto done;
if (FAILED(hr = IDirectInputDevice8_GetProperty( device, DIPROP_USERNAME, &prop_username.diph )))
WARN( "Failed to get device capabilities, hr %#lx\n", hr );
else if ((params->flags & DIEDBSFL_THISUSER) && *params->username && wcscmp( params->username, prop_username.wsz ))
goto done;
else if ((params->flags & DIEDBSFL_AVAILABLEDEVICES) && *prop_username.wsz)
goto done;
IDirectInputDevice_AddRef( device );
params->devices[params->device_count++] = device;
done:
IDirectInputDevice8_Release( device );
return ret;
}
struct enum_device_by_semantics_params
struct enum_device_object_semantics_params
{
IDirectInput8W *iface;
const WCHAR *username;
DIDEVICEINSTANCEW instance;
DIACTIONFORMATW *format;
DWORD flags;
DIDEVICEINSTANCEW *instances;
DWORD instance_count;
};
static BOOL CALLBACK enum_device_by_semantics( const DIDEVICEINSTANCEW *instance, void *context )
static BOOL CALLBACK enum_device_object_semantics( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
{
struct enum_device_by_semantics_params *params = context;
struct dinput *impl = impl_from_IDirectInput8W( params->iface );
struct enum_device_object_semantics_params *params = args;
DIACTIONFORMATW *format = params->format;
UINT i;
if (should_enumerate_device( params->username, params->flags, &impl->device_players, &instance->guidInstance ))
for (i = 0; format && i < format->dwNumActions; i++)
{
params->instance_count++;
params->instances = realloc( params->instances, sizeof(DIDEVICEINSTANCEW) * params->instance_count );
params->instances[params->instance_count - 1] = *instance;
DIOBJECTDATAFORMAT object_format = {.dwType = obj->dwType, .dwOfs = obj->dwOfs};
BYTE dev_type = params->instance.dwDevType & 0xf;
DIACTIONW *action = format->rgoAction + i;
if (!device_object_matches_semantic( &params->instance, &object_format, action->dwSemantic, FALSE )) continue;
if (!(action->dwSemantic & 0x4000)) params->flags |= DIEDBS_MAPPEDPRI1;
else if (dev_type != DIDEVTYPE_KEYBOARD && dev_type != DIDEVTYPE_MOUSE) params->flags |= DIEDBS_MAPPEDPRI2;
}
return DIENUM_CONTINUE;
......@@ -505,18 +509,13 @@ static BOOL CALLBACK enum_device_by_semantics( const DIDEVICEINSTANCEW *instance
static HRESULT WINAPI dinput8_EnumDevicesBySemantics( IDirectInput8W *iface, const WCHAR *username, DIACTIONFORMATW *action_format,
LPDIENUMDEVICESBYSEMANTICSCBW callback, void *context, DWORD flags )
{
struct enum_device_by_semantics_params params = {.iface = iface, .username = username, .flags = flags};
DWORD callbackFlags, enum_flags = DIEDFL_ATTACHEDONLY | (flags & DIEDFL_FORCEFEEDBACK);
static const GUID *guids[2] = {&GUID_SysKeyboard, &GUID_SysMouse};
static const DWORD actionMasks[] = {DIKEYBOARD_MASK, DIMOUSE_MASK};
struct enum_device_by_semantics_params params = {.iface = iface, .username = username ? username : L"", .flags = flags};
DWORD enum_flags = DIEDFL_ATTACHEDONLY | (flags & DIEDFL_FORCEFEEDBACK);
struct dinput *impl = impl_from_IDirectInput8W( iface );
IDirectInputDevice8W *device;
DIDEVICEINSTANCEW didevi;
unsigned int i = 0;
HRESULT hr;
int remain;
FIXME( "iface %p, username %s, action_format %p, callback %p, context %p, flags %#lx stub!\n",
TRACE( "iface %p, username %s, action_format %p, callback %p, context %p, flags %#lx\n",
iface, debugstr_w(username), action_format, callback, context, flags );
if (!action_format) return DIERR_INVALIDPARAM;
......@@ -531,64 +530,35 @@ static HRESULT WINAPI dinput8_EnumDevicesBySemantics( IDirectInput8W *iface, con
action->dwObjID, action->dwHow, debugstr_w(action->lptszActionName) );
}
didevi.dwSize = sizeof(didevi);
hr = IDirectInput8_EnumDevices( &impl->IDirectInput8W_iface, DI8DEVCLASS_GAMECTRL,
enum_device_by_semantics, &params, enum_flags );
if (FAILED(hr))
if (FAILED(hr = IDirectInput8_EnumDevices( &impl->IDirectInput8W_iface, DI8DEVCLASS_ALL,
enum_device_by_semantics, &params, enum_flags )))
{
free( params.instances );
return hr;
WARN( "Failed to enumerate devices, hr %#lx\n", hr );
goto cleanup;
}
remain = params.instance_count;
/* Add keyboard and mouse to remaining device count */
if (!(flags & DIEDBSFL_FORCEFEEDBACK))
while (params.device_count--)
{
for (i = 0; i < ARRAY_SIZE(guids); i++)
{
if (should_enumerate_device( username, flags, &impl->device_players, guids[i] )) remain++;
}
}
for (i = 0; i < params.instance_count; i++)
{
callbackFlags = diactionformat_priorityW( action_format, action_format->dwGenre );
IDirectInput_CreateDevice( iface, &params.instances[i].guidInstance, &device, NULL );
if (callback( &params.instances[i], device, callbackFlags, --remain, context ) == DIENUM_STOP)
{
free( params.instances );
IDirectInputDevice_Release( device );
return DI_OK;
}
IDirectInputDevice_Release( device );
}
free( params.instances );
if (flags & DIEDBSFL_FORCEFEEDBACK) return DI_OK;
/* Enumerate keyboard and mouse */
for (i = 0; i < ARRAY_SIZE(guids); i++)
{
if (should_enumerate_device( username, flags, &impl->device_players, guids[i] ))
{
callbackFlags = diactionformat_priorityW( action_format, actionMasks[i] );
IDirectInput_CreateDevice( iface, guids[i], &device, NULL );
IDirectInputDevice_GetDeviceInfo( device, &didevi );
if (callback( &didevi, device, callbackFlags, --remain, context ) == DIENUM_STOP)
{
IDirectInputDevice_Release( device );
return DI_OK;
}
IDirectInputDevice_Release( device );
}
struct enum_device_object_semantics_params object_params = {.instance = {.dwSize = sizeof(DIDEVICEINSTANCEW)}, .format = action_format};
IDirectInputDevice8W *device = params.devices[params.device_count];
BOOL ret = DIENUM_STOP;
if (FAILED(hr = IDirectInputDevice8_GetDeviceInfo( device, &object_params.instance )))
WARN( "Failed to get device %p info, hr %#lx\n", device, hr );
else if (FAILED(hr = IDirectInputDevice8_EnumObjects( device, enum_device_object_semantics, &object_params, DIDFT_ALL )))
WARN( "Failed to enumerate device %p objects, hr %#lx\n", device, hr );
else
ret = callback( &object_params.instance, device, object_params.flags, params.device_count, context );
IDirectInputDevice8_Release( device );
if (ret == DIENUM_STOP) goto cleanup;
}
return DI_OK;
cleanup:
while (params.device_count--) IDirectInputDevice8_Release( params.devices[params.device_count] );
return hr;
}
static HRESULT WINAPI dinput8_ConfigureDevices( IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK callback,
......
......@@ -445,7 +445,7 @@ static BOOL CALLBACK enum_devices_by_semantic( const DIDEVICEINSTANCEW *instance
if (remaining == 2)
{
expect_instance = &expect_joystick;
todo_wine ok( flags == (context ? 3 : 0), "got flags %#lx\n", flags );
ok( flags == (context ? 3 : 0), "got flags %#lx\n", flags );
}
else if (remaining == 1)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment