Authors: Ove Kaaven <ovek@transgaming.com>, Gavriel State <gav@transgaming.com>

Implemented circular buffering for the dinput mouse device.
Mapped the mouse warp on the center of the cooperative window, which
should make windowed games work better in managed mode.
This commit is contained in:
Alexandre Julliard 2001-01-28 23:14:25 +00:00
parent d4b933e7d2
commit e81843bb61
5 changed files with 81 additions and 70 deletions

View File

@ -34,16 +34,19 @@ extern DataFormat *create_DataFormat(DIDATAFORMAT *wine_format, LPCDIDATAFORMAT
{ \ { \
/* If queue_len > 0, queuing is requested -> TRACE the event queued */ \ /* If queue_len > 0, queuing is requested -> TRACE the event queued */ \
if (This->queue_len > 0) { \ if (This->queue_len > 0) { \
TRACE(" queueing %d at offset %d (queue pos %d / size %d)\n", \ DWORD nq; \
TRACE(" queueing %d at offset %d (queue head %d / size %d)\n", \
(int) (data), (int) (offset), \ (int) (data), (int) (offset), \
(int) (This->queue_pos), (int) (This->queue_len)); \ (int) (This->queue_head), (int) (This->queue_len)); \
\ \
if ((offset >= 0) && (This->queue_pos < This->queue_len)) { \ nq = This->queue_head+1; \
This->data_queue[This->queue_pos].dwOfs = offset; \ while (nq >= This->queue_len) nq -= This->queue_len; \
This->data_queue[This->queue_pos].dwData = data; \ if ((offset >= 0) && (nq != This->queue_tail)) { \
This->data_queue[This->queue_pos].dwTimeStamp = xtime; \ This->data_queue[This->queue_head].dwOfs = offset; \
This->data_queue[This->queue_pos].dwSequence = seq; \ This->data_queue[This->queue_head].dwData = data; \
This->queue_pos++; \ This->data_queue[This->queue_head].dwTimeStamp = xtime; \
This->data_queue[This->queue_head].dwSequence = seq; \
This->queue_head = nq; \
} \ } \
} \ } \
} }

View File

@ -113,7 +113,7 @@ HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPU
* IDirectInputA_EnumDevices * IDirectInputA_EnumDevices
*/ */
static HRESULT WINAPI IDirectInputAImpl_EnumDevices( static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
LPVOID pvRef, DWORD dwFlags LPVOID pvRef, DWORD dwFlags
) )
{ {
@ -133,13 +133,13 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
return 0; return 0;
} }
static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface) static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
{ {
ICOM_THIS(IDirectInputAImpl,iface); ICOM_THIS(IDirectInputAImpl,iface);
return ++(This->ref); return ++(This->ref);
} }
static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface) static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
{ {
ICOM_THIS(IDirectInputAImpl,iface); ICOM_THIS(IDirectInputAImpl,iface);
if (!(--This->ref)) { if (!(--This->ref)) {
@ -150,7 +150,7 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
} }
static HRESULT WINAPI IDirectInputAImpl_CreateDevice( static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev, LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
LPUNKNOWN punk LPUNKNOWN punk
) { ) {
ICOM_THIS(IDirectInputAImpl,iface); ICOM_THIS(IDirectInputAImpl,iface);
@ -173,7 +173,7 @@ static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
} }
static HRESULT WINAPI IDirectInputAImpl_QueryInterface( static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj LPDIRECTINPUT7A iface,REFIID riid,LPVOID *ppobj
) { ) {
ICOM_THIS(IDirectInputAImpl,iface); ICOM_THIS(IDirectInputAImpl,iface);
@ -193,12 +193,12 @@ static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
} }
static HRESULT WINAPI IDirectInputAImpl_Initialize( static HRESULT WINAPI IDirectInputAImpl_Initialize(
LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x LPDIRECTINPUT7A iface,HINSTANCE hinst,DWORD x
) { ) {
return DIERR_ALREADYINITIALIZED; return DIERR_ALREADYINITIALIZED;
} }
static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface, static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface,
REFGUID rguid) { REFGUID rguid) {
ICOM_THIS(IDirectInputAImpl,iface); ICOM_THIS(IDirectInputAImpl,iface);
@ -207,7 +207,7 @@ static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
return DI_OK; return DI_OK;
} }
static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface, static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
HWND hwndOwner, HWND hwndOwner,
DWORD dwFlags) { DWORD dwFlags) {
ICOM_THIS(IDirectInputAImpl,iface); ICOM_THIS(IDirectInputAImpl,iface);

View File

@ -59,7 +59,7 @@ struct JoystickAImpl
HANDLE hEvent; HANDLE hEvent;
LONG lMin,lMax,deadzone; LONG lMin,lMax,deadzone;
LPDIDEVICEOBJECTDATA data_queue; LPDIDEVICEOBJECTDATA data_queue;
int queue_pos, queue_len; int queue_head, queue_tail, queue_len;
DIJOYSTATE js; DIJOYSTATE js;
}; };
@ -287,7 +287,8 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceState(
FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len); FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
} }
memcpy(ptr,&(This->js),len); memcpy(ptr,&(This->js),len);
This->queue_pos = 0; This->queue_head = 0;
This->queue_tail = 0;
return 0; return 0;
} }

View File

@ -75,7 +75,7 @@ struct JoystickAImpl
LPDIDATAFORMAT df; LPDIDATAFORMAT df;
HANDLE hEvent; HANDLE hEvent;
LPDIDEVICEOBJECTDATA data_queue; LPDIDEVICEOBJECTDATA data_queue;
int queue_pos, queue_len; int queue_head, queue_tail, queue_len;
DIJOYSTATE js; DIJOYSTATE js;
/* data returned by the EVIOCGABS() ioctl */ /* data returned by the EVIOCGABS() ioctl */
@ -504,7 +504,8 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceState(
FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len); FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
} }
memcpy(ptr,&(This->js),len); memcpy(ptr,&(This->js),len);
This->queue_pos = 0; This->queue_head = 0;
This->queue_tail = 0;
return 0; return 0;
} }

View File

@ -109,9 +109,10 @@ struct SysMouseAImpl
LPMOUSE_EVENT_PROC prev_handler; LPMOUSE_EVENT_PROC prev_handler;
HWND win; HWND win;
DWORD dwCoopLevel; DWORD dwCoopLevel;
POINT mapped_center;
DWORD win_centerX, win_centerY; DWORD win_centerX, win_centerY;
LPDIDEVICEOBJECTDATA data_queue; LPDIDEVICEOBJECTDATA data_queue;
int queue_pos, queue_len; int queue_head, queue_tail, queue_len;
WARP_STATUS need_warp; WARP_STATUS need_warp;
int acquired; int acquired;
HANDLE hEvent; HANDLE hEvent;
@ -259,6 +260,8 @@ static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
_dump_cooperativelevel_DI(dwflags); _dump_cooperativelevel_DI(dwflags);
/* Store the window which asks for the mouse */ /* Store the window which asks for the mouse */
if (!hwnd)
hwnd = GetDesktopWindow();
This->win = hwnd; This->win = hwnd;
This->dwCoopLevel = dwflags; This->dwCoopLevel = dwflags;
@ -349,7 +352,7 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
} else { } else {
/* Now, warp handling */ /* Now, warp handling */
if ((This->need_warp == WARP_STARTED) && if ((This->need_warp == WARP_STARTED) &&
(posX == This->win_centerX) && (posX == This->win_centerX)) { (posX == This->mapped_center.x) && (posY == This->mapped_center.y)) {
/* Warp has been done... */ /* Warp has been done... */
This->need_warp = WARP_DONE; This->need_warp = WARP_DONE;
goto end; goto end;
@ -365,13 +368,13 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
} else { } else {
/* This is the first time the event handler has been called after a /* This is the first time the event handler has been called after a
GetData of GetState. */ GetData of GetState. */
if (posX != This->win_centerX) { if (posX != This->mapped_center.x) {
GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->win_centerX, xtime, (This->dinput->evsequence)++); GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->mapped_center.x, xtime, (This->dinput->evsequence)++);
This->need_warp = WARP_NEEDED; This->need_warp = WARP_NEEDED;
} }
if (posY != This->win_centerY) { if (posY != This->mapped_center.y) {
GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->win_centerY, xtime, (This->dinput->evsequence)++); GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->mapped_center.y, xtime, (This->dinput->evsequence)++);
This->need_warp = WARP_NEEDED; This->need_warp = WARP_NEEDED;
} }
} }
@ -384,8 +387,8 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
This->m_state.lX = posX; This->m_state.lX = posX;
This->m_state.lY = posY; This->m_state.lY = posY;
} else { } else {
This->m_state.lX = posX - This->win_centerX; This->m_state.lX = posX - This->mapped_center.x;
This->m_state.lY = posY - This->win_centerY; This->m_state.lY = posY - This->mapped_center.y;
} }
} else { } else {
/* Mouse reporting is in relative mode */ /* Mouse reporting is in relative mode */
@ -500,7 +503,7 @@ static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
TRACE("(this=%p)\n",This); TRACE("(this=%p)\n",This);
if (This->acquired == 0) { if (This->acquired == 0) {
POINT point; POINT point;
/* This stores the current mouse handler. */ /* This stores the current mouse handler. */
This->prev_handler = mouse_event; This->prev_handler = mouse_event;
@ -533,11 +536,11 @@ static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
/* Warp the mouse to the center of the window */ /* Warp the mouse to the center of the window */
if (This->absolute == 0) { if (This->absolute == 0) {
TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY); This->mapped_center.x = This->win_centerX;
point.x = This->win_centerX; This->mapped_center.y = This->win_centerY;
point.y = This->win_centerY; MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1); TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
SetCursorPos( point.x, point.y ); SetCursorPos( This->mapped_center.x, This->mapped_center.y );
#ifdef MOUSE_HACK #ifdef MOUSE_HACK
This->need_warp = WARP_DONE; This->need_warp = WARP_DONE;
#else #else
@ -602,13 +605,11 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
/* Check if we need to do a mouse warping */ /* Check if we need to do a mouse warping */
if (This->need_warp == WARP_NEEDED) { if (This->need_warp == WARP_NEEDED) {
POINT point; This->mapped_center.x = This->win_centerX;
This->mapped_center.y = This->win_centerY;
TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY); MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
point.x = This->win_centerX; TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
point.y = This->win_centerY; SetCursorPos( This->mapped_center.x, This->mapped_center.y );
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
SetCursorPos( point.x, point.y );
#ifdef MOUSE_HACK #ifdef MOUSE_HACK
This->need_warp = WARP_DONE; This->need_warp = WARP_DONE;
@ -636,52 +637,56 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
DWORD flags DWORD flags
) { ) {
ICOM_THIS(SysMouseAImpl,iface); ICOM_THIS(SysMouseAImpl,iface);
DWORD nqpos = 0; DWORD len, nqtail;
EnterCriticalSection(&(This->crit)); EnterCriticalSection(&(This->crit));
TRACE("(%p)->(dods=%ld,dod=%p,entries=%ld,fl=0x%08lx)\n",This,dodsize,dod,*entries,flags); TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
+ (This->queue_head - This->queue_tail);
if (len > *entries) len = *entries;
if (dod == NULL) { if (dod == NULL) {
*entries = This->queue_pos; *entries = len;
nqpos = 0; nqtail = This->queue_tail + len;
while (nqtail >= This->queue_len) nqtail -= This->queue_len;
} else { } else {
/* Check for buffer overflow */
if (This->queue_pos > dodsize) {
FIXME("Buffer overflow not handled properly yet...\n");
This->queue_pos = dodsize;
}
if (dodsize != sizeof(DIDEVICEOBJECTDATA)) { if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
ERR("Wrong structure size !\n"); ERR("Wrong structure size !\n");
LeaveCriticalSection(&(This->crit)); LeaveCriticalSection(&(This->crit));
return DIERR_INVALIDPARAM; return DIERR_INVALIDPARAM;
} }
if (This->queue_pos) if (len)
TRACE("Application retrieving %d event(s).\n", This->queue_pos); TRACE("Application retrieving %ld event(s).\n", len);
/* Copy the buffered data into the application queue */ *entries = 0;
memcpy(dod, This->data_queue, This->queue_pos * dodsize); nqtail = This->queue_tail;
*entries = This->queue_pos; while (len) {
DWORD span = ((This->queue_head < nqtail) ? This->queue_len : This->queue_head)
/* Reset the event queue */ - nqtail;
nqpos = 0; if (span > len) span = len;
/* Copy the buffered data into the application queue */
memcpy(dod + *entries, This->data_queue + nqtail, span * dodsize);
/* Advance position */
nqtail += span;
if (nqtail >= This->queue_len) nqtail -= This->queue_len;
*entries += span;
len -= span;
}
} }
if (!(flags & DIGDD_PEEK)) if (!(flags & DIGDD_PEEK))
This->queue_pos = nqpos; This->queue_tail = nqtail;
LeaveCriticalSection(&(This->crit)); LeaveCriticalSection(&(This->crit));
TRACE("returing *entries = %ld\n",*entries);
/* Check if we need to do a mouse warping */ /* Check if we need to do a mouse warping */
if (This->need_warp == WARP_NEEDED) { if (This->need_warp == WARP_NEEDED) {
POINT point; This->mapped_center.x = This->win_centerX;
This->mapped_center.y = This->win_centerY;
TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY); MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
point.x = This->win_centerX; TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
point.y = This->win_centerY; SetCursorPos( This->mapped_center.x, This->mapped_center.y );
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
SetCursorPos( point.x, point.y );
#ifdef MOUSE_HACK #ifdef MOUSE_HACK
This->need_warp = WARP_DONE; This->need_warp = WARP_DONE;
@ -712,7 +717,8 @@ static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0, This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
pd->dwData * sizeof(DIDEVICEOBJECTDATA)); pd->dwData * sizeof(DIDEVICEOBJECTDATA));
This->queue_pos = 0; This->queue_head = 0;
This->queue_tail = 0;
This->queue_len = pd->dwData; This->queue_len = pd->dwData;
break; break;
} }