📄 mouse.c
字号:
memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
/* Prepare all the data-conversion filters */
This->wine_df = create_DataFormat(&(Wine_InternalMouseFormat), df, This->offset_array);
return DI_OK;
}
/* low-level mouse hook */
static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lparam )
{
LRESULT ret;
MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
SysMouseImpl* This = (SysMouseImpl*) current_lock;
DWORD dwCoop;
static long last_event = 0;
int wdata;
long lasttime = 0;
if (code != HC_ACTION) return CallNextHookEx( This->hook, code, wparam, lparam );
EnterCriticalSection(&(This->crit));
dwCoop = This->dwCoopLevel;
/* Only allow mouse events every 10 ms.
* This is to allow the cursor to start acceleration before
* the warps happen. But if it involves a mouse button event we
* allow it since we don't want to lose the clicks.
*/
#ifndef __REACTOS__
if (((GetCurrentTime() - last_event) < 10)
&& wparam == WM_MOUSEMOVE)
goto end;
else last_event = GetCurrentTime();
#else
lasttime = GetCurrentTime() - last_event;
if ((lasttime) < 1)
goto end;
else if ((lasttime) >= 10)
last_event = GetCurrentTime();
#endif
/* Mouse moved -> send event if asked */
if (This->hEvent)
SetEvent(This->hEvent);
if (wparam == WM_MOUSEMOVE) {
if (This->absolute) {
if (hook->pt.x != This->prevX)
GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x, hook->time, 0);
if (hook->pt.y != This->prevY)
GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y, hook->time, 0);
} else {
/* Now, warp handling */
if ((This->need_warp == WARP_STARTED) &&
(hook->pt.x == This->mapped_center.x) && (hook->pt.y == This->mapped_center.y)) {
/* Warp has been done... */
This->need_warp = WARP_DONE;
goto end;
}
/* Relative mouse input with absolute mouse event : the real fun starts here... */
if ((This->need_warp == WARP_NEEDED) ||
(This->need_warp == WARP_STARTED)) {
if (hook->pt.x != This->prevX)
GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x - This->prevX,
hook->time, (This->dinput->evsequence)++);
if (hook->pt.y != This->prevY)
GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y - This->prevY,
hook->time, (This->dinput->evsequence)++);
} else {
/* This is the first time the event handler has been called after a
GetDeviceData or GetDeviceState. */
if (hook->pt.x != This->mapped_center.x) {
GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x - This->mapped_center.x,
hook->time, (This->dinput->evsequence)++);
This->need_warp = WARP_NEEDED;
}
if (hook->pt.y != This->mapped_center.y) {
GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y - This->mapped_center.y,
hook->time, (This->dinput->evsequence)++);
This->need_warp = WARP_NEEDED;
}
}
}
This->prevX = hook->pt.x;
This->prevY = hook->pt.y;
if (This->absolute) {
This->m_state.lX = hook->pt.x;
This->m_state.lY = hook->pt.y;
} else {
This->m_state.lX = hook->pt.x - This->mapped_center.x;
This->m_state.lY = hook->pt.y - This->mapped_center.y;
}
}
TRACE(" msg %x pt %ld %ld (W=%d)\n",
wparam, hook->pt.x, hook->pt.y, (!This->absolute) && This->need_warp );
switch(wparam) {
case WM_LBUTTONDOWN:
GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x80,
hook->time, This->dinput->evsequence++);
This->m_state.rgbButtons[0] = 0x80;
break;
case WM_LBUTTONUP:
GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x00,
hook->time, This->dinput->evsequence++);
This->m_state.rgbButtons[0] = 0x00;
break;
case WM_RBUTTONDOWN:
GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x80,
hook->time, This->dinput->evsequence++);
This->m_state.rgbButtons[1] = 0x80;
break;
case WM_RBUTTONUP:
GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x00,
hook->time, This->dinput->evsequence++);
This->m_state.rgbButtons[1] = 0x00;
break;
case WM_MBUTTONDOWN:
GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x80,
hook->time, This->dinput->evsequence++);
This->m_state.rgbButtons[2] = 0x80;
break;
case WM_MBUTTONUP:
GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x00,
hook->time, This->dinput->evsequence++);
This->m_state.rgbButtons[2] = 0x00;
break;
case WM_MOUSEWHEEL:
wdata = (short)HIWORD(hook->mouseData);
GEN_EVENT(This->offset_array[WINE_MOUSE_Z_POSITION], wdata,
hook->time, This->dinput->evsequence++);
This->m_state.lZ += wdata;
break;
}
TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
This->m_state.lX, This->m_state.lY,
This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
end:
LeaveCriticalSection(&(This->crit));
if (dwCoop & DISCL_NONEXCLUSIVE) {
/* Pass the events down to previous handlers (e.g. win32 input) */
ret = CallNextHookEx( This->hook, code, wparam, lparam );
} else {
/* Ignore message */
ret = 1;
}
return ret;
}
static void dinput_window_check(SysMouseImpl* This) {
RECT rect;
DWORD centerX, centerY;
/* make sure the window hasn't moved */
GetWindowRect(This->win, &rect);
centerX = (rect.right - rect.left) / 2;
centerY = (rect.bottom - rect.top ) / 2;
if (This->win_centerX != centerX || This->win_centerY != centerY) {
This->win_centerX = centerX;
This->win_centerY = centerY;
}
This->mapped_center.x = This->win_centerX;
This->mapped_center.y = This->win_centerY;
MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
}
/******************************************************************************
* Acquire : gets exclusive control of the mouse
*/
static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
{
SysMouseImpl *This = (SysMouseImpl *)iface;
RECT rect;
POINT point;
TRACE("(this=%p)\n",This);
if (This->acquired)
return S_FALSE;
This->acquired = 1;
/* Store (in a global variable) the current lock */
current_lock = (IDirectInputDevice8A*)This;
/* Init the mouse state */
GetCursorPos( &point );
if (This->absolute) {
This->m_state.lX = point.x;
This->m_state.lY = point.y;
This->prevX = point.x;
This->prevY = point.y;
} else {
This->m_state.lX = 0;
This->m_state.lY = 0;
This->org_coords = point;
}
This->m_state.lZ = 0;
This->m_state.rgbButtons[0] = GetKeyState(VK_LBUTTON) & 0x80;
This->m_state.rgbButtons[1] = GetKeyState(VK_RBUTTON) & 0x80;
This->m_state.rgbButtons[2] = GetKeyState(VK_MBUTTON) & 0x80;
/* Install our mouse hook */
if (This->dwCoopLevel & DISCL_EXCLUSIVE)
ShowCursor(FALSE); /* hide cursor */
This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
/* Get the window dimension and find the center */
GetWindowRect(This->win, &rect);
This->win_centerX = (rect.right - rect.left) / 2;
This->win_centerY = (rect.bottom - rect.top ) / 2;
/* Warp the mouse to the center of the window */
if (This->absolute == 0) {
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
This->need_warp = WARP_STARTED;
#endif
}
return DI_OK;
}
/******************************************************************************
* Unacquire : frees the mouse
*/
static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
{
SysMouseImpl *This = (SysMouseImpl *)iface;
TRACE("(this=%p)\n",This);
if (0 == This->acquired) {
return DI_NOEFFECT;
}
/* Reinstall previous mouse event handler */
if (This->hook) {
UnhookWindowsHookEx( This->hook );
This->hook = 0;
if (This->dwCoopLevel & DISCL_EXCLUSIVE)
ShowCursor(TRUE); /* show cursor */
}
/* No more locks */
if (current_lock == (IDirectInputDevice8A*) This)
current_lock = NULL;
else
ERR("this(%p) != current_lock(%p)\n", This, current_lock);
/* Unacquire device */
This->acquired = 0;
/* And put the mouse cursor back where it was at acquire time */
if (This->absolute == 0) {
TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y);
SetCursorPos(This->org_coords.x, This->org_coords.y);
}
return DI_OK;
}
// if you call poll then to getdevicestate
// it did not send back right value in windows
int poll_mouse=0;
static HRESULT WINAPI SysMouseAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
{
int retValue = DI_OK;
if (poll_mouse==0) {
retValue=SysMouseAImpl_Acquire(iface);
poll_mouse=1;
if (retValue!=DI_OK) retValue=DIERR_NOTACQUIRED;
else retValue = DI_OK;
}
return retValue;
}
/******************************************************************************
* GetDeviceState : returns the "state" of the mouse.
*
* For the moment, only the "standard" return structure (DIMOUSESTATE) is
* supported.
*/
static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
) {
SysMouseImpl *This = (SysMouseImpl *)iface;
if(This->acquired == 0) return DIERR_NOTACQUIRED;
EnterCriticalSection(&(This->crit));
TRACE("(this=%p,0x%08lx,%p):\n", This, len, ptr);
TRACE("(X: %ld - Y: %ld - Z: %ld L: %02x M: %02x R: %02x)\n",
This->m_state.lX, This->m_state.lY, This->m_state.lZ,
This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
/* Copy the current mouse state */
fill_DataFormat(ptr, &(This->m_state), This->wine_df);
#ifdef __REACTOS__
// this fix windows bugs when
// some program calling on mouse poll
if (poll_mouse==1) poll_mouse=0;
else {
if (This->absolute == 0) {
This->m_state.lX = 0;
This->m_state.lY = 0;
This->m_state.lZ = 0;
}
}
#endif
/* Check if we need to do a mouse warping */
if (This->need_warp == WARP_NEEDED) {
dinput_window_check(This);
TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
if (mouse_set==0){
SetCursorPos( This->mapped_center.x, This->mapped_center.y );
mouse_set++;
}
#ifdef MOUSE_HACK
This->need_warp = WARP_DONE;
#else
This->need_warp = WARP_STARTED;
#endif
}
LeaveCriticalSection(&(This->crit));
return DI_OK;
}
/******************************************************************************
* GetDeviceData : gets buffered input data.
*/
static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
DWORD dodsize,
LPDIDEVICEOBJECTDATA dod,
LPDWORD entries,
DWORD flags
) {
SysMouseImpl *This = (SysMouseImpl *)iface;
DWORD len;
int nqtail = 0;
TRACE("(%p)->(dods=%ld,dod=%p,entries=%p (%ld)%s,fl=0x%08lx%s)\n",This,dodsize,dod,
entries, *entries,*entries == INFINITE ? " (INFINITE)" : "",
flags, (flags & DIGDD_PEEK) ? " (DIGDD_PEEK)": "" );
if (This->acquired == 0) {
WARN(" application tries to get data from an unacquired device !\n");
//return DIERR_NOTACQUIRED;
// windows does not get any data if
// we do not call manual to mouse Acquire
// this is only need if some apps calling on getdevice data direcly
// in windows GetdeviceData does always update first the data
// then return it.
SysMouseAImpl_Acquire(iface);
}
EnterCriticalSection(&(This->crit));
len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
+ (This->queue_head - This->queue_tail);
if ((*entries != INFINITE) && (len > *entries)) len = *entries;
if (dod == NULL) {
*entries = len;
if (!(flags & DIGDD_PEEK)) {
if (len)
TRACE("Application discarding %ld event(s).\n", len);
nqtail = This->queue_tail + len;
while (nqtail >= This->queue_len) nqtail -= This->queue_len;
} else {
TRACE("Telling application that %ld event(s) are in the queue.\n", len);
}
} else {
if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) {
ERR("Wrong structure size !\n");
LeaveCriticalSection(&(This->crit));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -