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 );