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).
This commit is contained in:
Marcus Meissner 1999-07-27 16:08:59 +00:00 committed by Alexandre Julliard
parent daed93ee99
commit bc2ad4a267
1 changed files with 98 additions and 76 deletions

View File

@ -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 @@ struct SysMouseAImpl
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 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
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 @@ static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
}
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 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
)
{
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 @@ static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
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 @@ static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
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 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
&& ((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 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
} else {
ERR("Mouse event not supported...\n");
LeaveCriticalSection(&(This->crit));
return ;
}
@ -780,26 +795,26 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
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 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
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 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
) {
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 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
}
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 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
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 @@ static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
break;
}
default:
WARN("Unknown type %ld\n",(DWORD)rguid);
FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
break;
}
}