Actually return the number of events in Mouse_GetDeviceData (fixes
Wing Commander Prophecy). Added timestamp and sequence generation,
critical section for mousedata. Disabled mouse warping in
GetDeviceData for now (generates excess mouse events).
diff --git a/windows/dinput.c b/windows/dinput.c
index 5759f01..36b4ba8 100644
--- a/windows/dinput.c
+++ b/windows/dinput.c
@@ -20,6 +20,7 @@
#include "config.h"
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <assert.h>
#ifdef HAVE_SYS_SIGNAL_H
@@ -76,20 +77,25 @@
ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
DWORD ref;
GUID guid;
+
+ LPDIDATAFORMAT df;
/* SysMouseAImpl */
BYTE absolute;
/* Previous position for relative moves */
- LONG prevX, prevY;
- LPMOUSE_EVENT_PROC prev_handler;
- HWND win;
- DWORD win_centerX, win_centerY;
- LPDIDEVICEOBJECTDATA data_queue;
- int queue_pos, queue_len;
- int need_warp;
- int acquired;
- HANDLE hEvent;
+ LONG prevX, prevY;
+ LPMOUSE_EVENT_PROC prev_handler;
+ HWND win;
+ DWORD win_centerX, win_centerY;
+ LPDIDEVICEOBJECTDATA data_queue;
+ int queue_pos, queue_len;
+ int need_warp;
+ int acquired;
+ HANDLE hEvent;
+ CRITICAL_SECTION crit;
};
+static int evsequence=0;
+
/* UIDs for Wine "drivers".
When enumerating each device supporting DInput, they have two UIDs :
@@ -161,43 +167,39 @@
LPVOID pvRef, DWORD dwFlags
)
{
- ICOM_THIS(IDirectInputAImpl,iface);
- DIDEVICEINSTANCEA devInstance;
- int ret;
+ ICOM_THIS(IDirectInputAImpl,iface);
+ DIDEVICEINSTANCEA devInstance;
+ int ret;
- TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
+ TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
- devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
-
- if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
- /* Return keyboard */
- devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
- devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
- devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
- strcpy(devInstance.tszInstanceName, "Keyboard");
- strcpy(devInstance.tszProductName, "Wine Keyboard");
-
- ret = lpCallback(&devInstance, pvRef);
- TRACE("Keyboard registered\n");
-
- if (ret == DIENUM_STOP)
- return 0;
- }
-
- if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
- /* Return mouse */
- devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
- devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
- devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
- strcpy(devInstance.tszInstanceName, "Mouse");
- strcpy(devInstance.tszProductName, "Wine Mouse");
-
- ret = lpCallback(&devInstance, pvRef);
- TRACE("Mouse registered\n");
- }
+ devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
+ if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
+ /* Return keyboard */
+ devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
+ devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
+ devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
+ strcpy(devInstance.tszInstanceName, "Keyboard");
+ strcpy(devInstance.tszProductName, "Wine Keyboard");
- /* Should also do joystick enumerations.... */
+ ret = lpCallback(&devInstance, pvRef);
+ TRACE("Keyboard registered\n");
+ if (ret == DIENUM_STOP)
+ return 0;
+ }
+ if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
+ /* Return mouse */
+ devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
+ devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
+ devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
+ strcpy(devInstance.tszInstanceName, "Mouse");
+ strcpy(devInstance.tszProductName, "Wine Mouse");
+
+ ret = lpCallback(&devInstance, pvRef);
+ TRACE("Mouse registered\n");
+ }
+ /* Should also do joystick enumerations.... */
return 0;
}
@@ -239,10 +241,12 @@
}
if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
(!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
- SysKeyboardAImpl* newDevice;
+ SysMouseAImpl* newDevice;
newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
newDevice->ref = 1;
newDevice->lpvtbl = &SysMouseAvt;
+ InitializeCriticalSection(&(newDevice->crit));
+ MakeCriticalSectionGlobal(&(newDevice->crit));
memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
*pdev=(IDirectInputDeviceA*)newDevice;
return DI_OK;
@@ -414,12 +418,19 @@
)
{
ICOM_THIS(SysKeyboardAImpl,iface);
+ HRESULT ret;
+ int i;
TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
This,dodsize,dod,entries,entries?*entries:0,flags);
- return KEYBOARD_Driver->pGetDIData(
+ ret=KEYBOARD_Driver->pGetDIData(
This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
+ for (i=0;i<*entries;i++) {
+ dod[i].dwTimeStamp = time(NULL);
+ dod[i].dwSequence = evsequence++;
+ }
+ return ret;
}
static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
@@ -652,6 +663,7 @@
mouse device) */
if (This->prev_handler != NULL)
MOUSE_Enable(This->prev_handler);
+ DeleteCriticalSection(&(This->crit));
HeapFree(GetProcessHeap(),0,This);
return 0;
@@ -733,29 +745,31 @@
else
ERR("Neither absolute nor relative flag set.");
+ This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
+ memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
return 0;
}
+#define GEN_EVENT(offset,data,xtime,seq) \
+{ \
+ if (This->queue_pos < This->queue_len) { \
+ This->data_queue[This->queue_pos].dwOfs = offset; \
+ This->data_queue[This->queue_pos].dwData = data; \
+ This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
+ This->data_queue[This->queue_pos].dwSequence = seq; \
+ This->queue_pos++; \
+ } \
+}
-
-#define GEN_EVENT(offset,data,time,seq) \
-{ \
- if (This->queue_pos < This->queue_len) { \
- This->data_queue[This->queue_pos].dwOfs = offset; \
- This->data_queue[This->queue_pos].dwData = data; \
- This->data_queue[This->queue_pos].dwTimeStamp = time; \
- This->data_queue[This->queue_pos].dwSequence = seq; \
- This->queue_pos++; \
- } \
- }
/* Our private mouse event handler */
static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
DWORD cButtons, DWORD dwExtraInfo )
{
- DWORD posX, posY, keyState, time, extra;
+ DWORD posX, posY, keyState, xtime, extra;
SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
+ EnterCriticalSection(&(This->crit));
/* Mouse moved -> send event if asked */
if (This->hEvent)
SetEvent(This->hEvent);
@@ -764,7 +778,7 @@
&& ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
keyState = wme->keyState;
- time = wme->time;
+ xtime = wme->time;
extra = (DWORD)wme->hWnd;
assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
@@ -772,6 +786,7 @@
posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
} else {
ERR("Mouse event not supported...\n");
+ LeaveCriticalSection(&(This->crit));
return ;
}
@@ -780,26 +795,26 @@
if ( dwFlags & MOUSEEVENTF_MOVE ) {
if (This->absolute) {
if (posX != This->prevX)
- GEN_EVENT(DIMOFS_X, posX, time, 0);
+ GEN_EVENT(DIMOFS_X, posX, xtime, 0);
if (posY != This->prevY)
- GEN_EVENT(DIMOFS_Y, posY, time, 0);
+ GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
} else {
/* Relative mouse input : the real fun starts here... */
if (This->need_warp) {
if (posX != This->prevX)
- GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
+ GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
if (posY != This->prevY)
- GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
+ GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
} else {
/* This is the first time the event handler has been called after a
GetData of GetState. */
if (posX != This->win_centerX) {
- GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
+ GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
This->need_warp = 1;
}
if (posY != This->win_centerY) {
- GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
+ GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
This->need_warp = 1;
}
}
@@ -809,43 +824,44 @@
if (TRACE_ON(dinput))
DPRINTF(" LD ");
- GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
+ GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
}
if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
if (TRACE_ON(dinput))
DPRINTF(" LU ");
- GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
+ GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
}
if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
if (TRACE_ON(dinput))
DPRINTF(" RD ");
- GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
+ GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
}
if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
if (TRACE_ON(dinput))
DPRINTF(" RU ");
- GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
+ GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
}
if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
if (TRACE_ON(dinput))
DPRINTF(" MD ");
- GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
+ GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
}
if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
if (TRACE_ON(dinput))
DPRINTF(" MU ");
- GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
+ GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
}
if (TRACE_ON(dinput))
DPRINTF("\n");
This->prevX = posX;
This->prevY = posY;
+ LeaveCriticalSection(&(This->crit));
}
@@ -983,11 +999,11 @@
) {
ICOM_THIS(SysMouseAImpl,iface);
- TRACE("(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
- This,dodsize,dod,entries,*entries,flags);
+ EnterCriticalSection(&(This->crit));
+ TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
if (flags & DIGDD_PEEK)
- TRACE("DIGDD_PEEK\n");
+ FIXME("DIGDD_PEEK\n");
if (dod == NULL) {
*entries = This->queue_pos;
@@ -1000,18 +1016,23 @@
}
if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
ERR("Wrong structure size !\n");
+ LeaveCriticalSection(&(This->crit));
return DIERR_INVALIDPARAM;
}
- TRACE("Application retrieving %d event(s).\n", This->queue_pos);
+ if (This->queue_pos)
+ TRACE("Application retrieving %d event(s).\n", This->queue_pos);
/* Copy the buffered data into the application queue */
memcpy(dod, This->data_queue, This->queue_pos * dodsize);
-
+ *entries = This->queue_pos;
+
/* Reset the event queue */
This->queue_pos = 0;
}
+ LeaveCriticalSection(&(This->crit));
+#if 0 /* FIXME: seems to create motion events, which fire back at us. */
/* Check if we need to do a mouse warping */
if (This->need_warp) {
POINT point;
@@ -1020,11 +1041,12 @@
point.x = This->win_centerX;
point.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
+
DISPLAY_MoveCursor(point.x, point.y);
This->need_warp = 0;
}
-
+#endif
return 0;
}
@@ -1059,7 +1081,7 @@
break;
}
default:
- WARN("Unknown type %ld\n",(DWORD)rguid);
+ FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
break;
}
}