Commit e81843bb authored by Alexandre Julliard's avatar Alexandre Julliard

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.
parent d4b933e7
......@@ -34,16 +34,19 @@ extern DataFormat *create_DataFormat(DIDATAFORMAT *wine_format, LPCDIDATAFORMAT
{ \
/* If queue_len > 0, queuing is requested -> TRACE the event queued */ \
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) (This->queue_pos), (int) (This->queue_len)); \
(int) (This->queue_head), (int) (This->queue_len)); \
\
if ((offset >= 0) && (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++; \
nq = This->queue_head+1; \
while (nq >= This->queue_len) nq -= This->queue_len; \
if ((offset >= 0) && (nq != This->queue_tail)) { \
This->data_queue[This->queue_head].dwOfs = offset; \
This->data_queue[This->queue_head].dwData = data; \
This->data_queue[This->queue_head].dwTimeStamp = xtime; \
This->data_queue[This->queue_head].dwSequence = seq; \
This->queue_head = nq; \
} \
} \
}
......
......@@ -113,7 +113,7 @@ HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPU
* IDirectInputA_EnumDevices
*/
static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
LPVOID pvRef, DWORD dwFlags
)
{
......@@ -133,13 +133,13 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
return 0;
}
static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
{
ICOM_THIS(IDirectInputAImpl,iface);
return ++(This->ref);
}
static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
{
ICOM_THIS(IDirectInputAImpl,iface);
if (!(--This->ref)) {
......@@ -150,7 +150,7 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
}
static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
LPUNKNOWN punk
) {
ICOM_THIS(IDirectInputAImpl,iface);
......@@ -173,7 +173,7 @@ static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
}
static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
LPDIRECTINPUT7A iface,REFIID riid,LPVOID *ppobj
) {
ICOM_THIS(IDirectInputAImpl,iface);
......@@ -193,12 +193,12 @@ static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
}
static HRESULT WINAPI IDirectInputAImpl_Initialize(
LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
LPDIRECTINPUT7A iface,HINSTANCE hinst,DWORD x
) {
return DIERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface,
REFGUID rguid) {
ICOM_THIS(IDirectInputAImpl,iface);
......@@ -207,7 +207,7 @@ static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
return DI_OK;
}
static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
HWND hwndOwner,
DWORD dwFlags) {
ICOM_THIS(IDirectInputAImpl,iface);
......
......@@ -59,7 +59,7 @@ struct JoystickAImpl
HANDLE hEvent;
LONG lMin,lMax,deadzone;
LPDIDEVICEOBJECTDATA data_queue;
int queue_pos, queue_len;
int queue_head, queue_tail, queue_len;
DIJOYSTATE js;
};
......@@ -287,7 +287,8 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceState(
FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
}
memcpy(ptr,&(This->js),len);
This->queue_pos = 0;
This->queue_head = 0;
This->queue_tail = 0;
return 0;
}
......
......@@ -75,7 +75,7 @@ struct JoystickAImpl
LPDIDATAFORMAT df;
HANDLE hEvent;
LPDIDEVICEOBJECTDATA data_queue;
int queue_pos, queue_len;
int queue_head, queue_tail, queue_len;
DIJOYSTATE js;
/* 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);
}
memcpy(ptr,&(This->js),len);
This->queue_pos = 0;
This->queue_head = 0;
This->queue_tail = 0;
return 0;
}
......
......@@ -109,9 +109,10 @@ struct SysMouseAImpl
LPMOUSE_EVENT_PROC prev_handler;
HWND win;
DWORD dwCoopLevel;
POINT mapped_center;
DWORD win_centerX, win_centerY;
LPDIDEVICEOBJECTDATA data_queue;
int queue_pos, queue_len;
int queue_head, queue_tail, queue_len;
WARP_STATUS need_warp;
int acquired;
HANDLE hEvent;
......@@ -259,6 +260,8 @@ static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
_dump_cooperativelevel_DI(dwflags);
/* Store the window which asks for the mouse */
if (!hwnd)
hwnd = GetDesktopWindow();
This->win = hwnd;
This->dwCoopLevel = dwflags;
......@@ -349,7 +352,7 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
} else {
/* Now, warp handling */
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... */
This->need_warp = WARP_DONE;
goto end;
......@@ -365,13 +368,13 @@ static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
} else {
/* This is the first time the event handler has been called after a
GetData of GetState. */
if (posX != This->win_centerX) {
GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->win_centerX, xtime, (This->dinput->evsequence)++);
if (posX != This->mapped_center.x) {
GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->mapped_center.x, xtime, (This->dinput->evsequence)++);
This->need_warp = WARP_NEEDED;
}
if (posY != This->win_centerY) {
GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->win_centerY, xtime, (This->dinput->evsequence)++);
if (posY != This->mapped_center.y) {
GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->mapped_center.y, xtime, (This->dinput->evsequence)++);
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.lY = posY;
} else {
This->m_state.lX = posX - This->win_centerX;
This->m_state.lY = posY - This->win_centerY;
This->m_state.lX = posX - This->mapped_center.x;
This->m_state.lY = posY - This->mapped_center.y;
}
} else {
/* Mouse reporting is in relative mode */
......@@ -500,7 +503,7 @@ static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
TRACE("(this=%p)\n",This);
if (This->acquired == 0) {
POINT point;
POINT point;
/* This stores the current mouse handler. */
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 */
if (This->absolute == 0) {
TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
point.x = This->win_centerX;
point.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
SetCursorPos( point.x, point.y );
This->mapped_center.x = This->win_centerX;
This->mapped_center.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
SetCursorPos( This->mapped_center.x, This->mapped_center.y );
#ifdef MOUSE_HACK
This->need_warp = WARP_DONE;
#else
......@@ -599,16 +602,14 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
This->m_state.lX = 0;
This->m_state.lY = 0;
}
/* Check if we need to do a mouse warping */
if (This->need_warp == WARP_NEEDED) {
POINT point;
TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
point.x = This->win_centerX;
point.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
SetCursorPos( point.x, point.y );
This->mapped_center.x = This->win_centerX;
This->mapped_center.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
SetCursorPos( This->mapped_center.x, This->mapped_center.y );
#ifdef MOUSE_HACK
This->need_warp = WARP_DONE;
......@@ -636,52 +637,56 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
DWORD flags
) {
ICOM_THIS(SysMouseAImpl,iface);
DWORD nqpos = 0;
DWORD len, nqtail;
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) {
*entries = This->queue_pos;
nqpos = 0;
*entries = len;
nqtail = This->queue_tail + len;
while (nqtail >= This->queue_len) nqtail -= This->queue_len;
} 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)) {
ERR("Wrong structure size !\n");
LeaveCriticalSection(&(This->crit));
return DIERR_INVALIDPARAM;
}
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 */
nqpos = 0;
if (len)
TRACE("Application retrieving %ld event(s).\n", len);
*entries = 0;
nqtail = This->queue_tail;
while (len) {
DWORD span = ((This->queue_head < nqtail) ? This->queue_len : This->queue_head)
- nqtail;
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))
This->queue_pos = nqpos;
This->queue_tail = nqtail;
LeaveCriticalSection(&(This->crit));
TRACE("returing *entries = %ld\n",*entries);
/* Check if we need to do a mouse warping */
if (This->need_warp == WARP_NEEDED) {
POINT point;
TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
point.x = This->win_centerX;
point.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
SetCursorPos( point.x, point.y );
This->mapped_center.x = This->win_centerX;
This->mapped_center.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
SetCursorPos( This->mapped_center.x, This->mapped_center.y );
#ifdef MOUSE_HACK
This->need_warp = WARP_DONE;
......@@ -712,7 +717,8 @@ static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
pd->dwData * sizeof(DIDEVICEOBJECTDATA));
This->queue_pos = 0;
This->queue_head = 0;
This->queue_tail = 0;
This->queue_len = pd->dwData;
break;
}
......
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