📄 main.c
字号:
/* DirectInput Mouse device * * Copyright 1998 Marcus Meissner * Copyright 1998,1999 Lionel Ulmer * Copyright 2000-2001 TransGaming Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "config.h"#include "wine/port.h"#include <stdarg.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "winerror.h"#include "dinput.h"#include "dinput_private.h"#include "device_private.h"#include "wine/debug.h"#include "wine/unicode.h"#define MOUSE_HACKWINE_DEFAULT_DEBUG_CHANNEL(dinput);/* Wine mouse driver object instances */#define WINE_MOUSE_X_AXIS_INSTANCE 0x0001#define WINE_MOUSE_Y_AXIS_INSTANCE 0x0002#define WINE_MOUSE_Z_AXIS_INSTANCE 0x0004#define WINE_MOUSE_L_BUTTON_INSTANCE 0x0008#define WINE_MOUSE_R_BUTTON_INSTANCE 0x0010#define WINE_MOUSE_M_BUTTON_INSTANCE 0x0020/* ------------------------------- *//* Wine mouse internal data format *//* ------------------------------- *//* Constants used to access the offset array */#define WINE_MOUSE_X_POSITION 0#define WINE_MOUSE_Y_POSITION 1#define WINE_MOUSE_Z_POSITION 2#define WINE_MOUSE_L_POSITION 3#define WINE_MOUSE_R_POSITION 4#define WINE_MOUSE_M_POSITION 5typedef struct { LONG lX; LONG lY; LONG lZ; BYTE rgbButtons[4];} Wine_InternalMouseData;#define WINE_INTERNALMOUSE_NUM_OBJS 6static DIOBJECTDATAFORMAT Wine_InternalMouseObjectFormat[WINE_INTERNALMOUSE_NUM_OBJS] = { { &GUID_XAxis, FIELD_OFFSET(Wine_InternalMouseData, lX), DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 }, { &GUID_YAxis, FIELD_OFFSET(Wine_InternalMouseData, lY), DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 }, { &GUID_ZAxis, FIELD_OFFSET(Wine_InternalMouseData, lZ), DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 }, { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 0, DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }, { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 1, DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }, { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 2, DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }};static DIDATAFORMAT Wine_InternalMouseFormat = { 0, /* dwSize - unused */ 0, /* dwObjsize - unused */ 0, /* dwFlags - unused */ sizeof(Wine_InternalMouseData), WINE_INTERNALMOUSE_NUM_OBJS, /* dwNumObjs */ Wine_InternalMouseObjectFormat};static ICOM_VTABLE(IDirectInputDevice8A) SysMouseAvt;static ICOM_VTABLE(IDirectInputDevice8W) SysMouseWvt;typedef struct SysMouseImpl SysMouseImpl;typedef enum { WARP_NEEDED, /* Warping is needed */ WARP_STARTED, /* Warping has been done, waiting for the warp event */ WARP_DONE /* Warping has been done */} WARP_STATUS;struct SysMouseImpl{ LPVOID lpVtbl; DWORD ref; GUID guid; IDirectInputImpl *dinput; /* The current data format and the conversion between internal and external data formats */ LPDIDATAFORMAT df; DataFormat *wine_df; int offset_array[WINE_INTERNALMOUSE_NUM_OBJS]; /* SysMouseAImpl */ BYTE absolute; /* Previous position for relative moves */ LONG prevX, prevY; HHOOK hook; HWND win; DWORD dwCoopLevel; POINT mapped_center; DWORD win_centerX, win_centerY; LPDIDEVICEOBJECTDATA data_queue; int queue_head, queue_tail, queue_len; /* warping: whether we need to move mouse back to middle once we * reach window borders (for e.g. shooters, "surface movement" games) */ WARP_STATUS need_warp; int acquired; HANDLE hEvent; CRITICAL_SECTION crit; /* This is for mouse reporting. */ Wine_InternalMouseData m_state;};/* FIXME: This is ugly and not thread safe :/ */static IDirectInputDevice8A* current_lock = NULL;static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */ 0x9e573ed8, 0x7734, 0x11d2, {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}};static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, int version) { DWORD dwSize; DIDEVICEINSTANCEA ddi; dwSize = lpddi->dwSize; TRACE("%ld %p\n", dwSize, lpddi); memset(lpddi, 0, dwSize); memset(&ddi, 0, sizeof(ddi)); ddi.dwSize = dwSize; ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */ ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */ if (version >= 8) ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8); else ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8); strcpy(ddi.tszInstanceName, "Mouse"); strcpy(ddi.tszProductName, "Wine Mouse"); memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));}static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, int version) { DWORD dwSize; DIDEVICEINSTANCEW ddi; dwSize = lpddi->dwSize; TRACE("%ld %p\n", dwSize, lpddi); memset(lpddi, 0, dwSize); memset(&ddi, 0, sizeof(ddi)); ddi.dwSize = dwSize; ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */ ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */ if (version >= 8) ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8); else ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8); MultiByteToWideChar(CP_ACP, 0, "Mouse", -1, ddi.tszInstanceName, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, "Wine Mouse", -1, ddi.tszProductName, MAX_PATH); memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));}static BOOL mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version){ if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_MOUSE) && (version < 8)) || ((dwDevType == DI8DEVTYPE_MOUSE) && (version >= 8))) { TRACE("Enumerating the mouse device\n"); fill_mouse_dideviceinstanceA(lpddi, version); return TRUE; } return FALSE;}static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version){ if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_MOUSE) && (version < 8)) || ((dwDevType == DI8DEVTYPE_MOUSE) && (version >= 8))) { TRACE("Enumerating the mouse device\n"); fill_mouse_dideviceinstanceW(lpddi, version); return TRUE; } return FALSE;}static SysMouseImpl *alloc_device(REFGUID rguid, LPVOID mvt, IDirectInputImpl *dinput){ int offset_array[WINE_INTERNALMOUSE_NUM_OBJS] = { FIELD_OFFSET(Wine_InternalMouseData, lX), FIELD_OFFSET(Wine_InternalMouseData, lY), FIELD_OFFSET(Wine_InternalMouseData, lZ), FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 0, FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 1, FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 2 }; SysMouseImpl* newDevice; newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl)); newDevice->ref = 1; newDevice->lpVtbl = mvt; InitializeCriticalSection(&(newDevice->crit)); memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); /* Per default, Wine uses its internal data format */ newDevice->df = &Wine_InternalMouseFormat; memcpy(newDevice->offset_array, offset_array, WINE_INTERNALMOUSE_NUM_OBJS * sizeof(int)); newDevice->wine_df = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat)); newDevice->wine_df->size = 0; newDevice->wine_df->internal_format_size = Wine_InternalMouseFormat.dwDataSize; newDevice->wine_df->dt = NULL; newDevice->dinput = dinput; return newDevice;}static HRESULT mousedev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev){ if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */ (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */ if ((riid == NULL) || IsEqualGUID(&IID_IDirectInputDeviceA,riid) || IsEqualGUID(&IID_IDirectInputDevice2A,riid) || IsEqualGUID(&IID_IDirectInputDevice7A,riid) || IsEqualGUID(&IID_IDirectInputDevice8A,riid)) { *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysMouseAvt, dinput); TRACE("Creating a Mouse device (%p)\n", *pdev); return DI_OK; } else return DIERR_NOINTERFACE; } return DIERR_DEVICENOTREG;}static HRESULT mousedev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev){ if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */ (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */ if ((riid == NULL) || IsEqualGUID(&IID_IDirectInputDeviceW,riid) || IsEqualGUID(&IID_IDirectInputDevice2W,riid) || IsEqualGUID(&IID_IDirectInputDevice7W,riid) || IsEqualGUID(&IID_IDirectInputDevice8W,riid)) { *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysMouseWvt, dinput); TRACE("Creating a Mouse device (%p)\n", *pdev); return DI_OK; } else return DIERR_NOINTERFACE; } return DIERR_DEVICENOTREG;}static dinput_device mousedev = { 100, mousedev_enum_deviceA, mousedev_enum_deviceW, mousedev_create_deviceA, mousedev_create_deviceW};DECL_GLOBAL_CONSTRUCTOR(mousedev_register) { dinput_register_device(&mousedev); }/****************************************************************************** * SysMouseA (DInput Mouse support) *//****************************************************************************** * Release : release the mouse buffer. */static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE8A iface){ ICOM_THIS(SysMouseImpl,iface); This->ref--; if (This->ref) return This->ref; /* Free the data queue */ if (This->data_queue != NULL) HeapFree(GetProcessHeap(),0,This->data_queue); if (This->hook) { UnhookWindowsHookEx( This->hook ); if (This->dwCoopLevel & DISCL_EXCLUSIVE) ShowCursor(TRUE); /* show cursor */ } DeleteCriticalSection(&(This->crit)); /* Free the DataFormat */ if (This->df != &(Wine_InternalMouseFormat)) { HeapFree(GetProcessHeap(), 0, This->df->rgodf); HeapFree(GetProcessHeap(), 0, This->df); } HeapFree(GetProcessHeap(),0,This); return DI_OK;}/****************************************************************************** * SetCooperativeLevel : store the window in which we will do our * grabbing. */static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel( LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags){ ICOM_THIS(SysMouseImpl,iface); TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags); if (TRACE_ON(dinput)) { TRACE(" cooperative level : "); _dump_cooperativelevel_DI(dwflags); } /* Store the window which asks for the mouse */ if (!hwnd) hwnd = GetDesktopWindow(); This->win = hwnd; This->dwCoopLevel = dwflags; return DI_OK;}/****************************************************************************** * SetDataFormat : the application can choose the format of the data * the device driver sends back with GetDeviceState. * * For the moment, only the "standard" configuration (c_dfDIMouse) is supported * in absolute and relative mode. */static HRESULT WINAPI SysMouseAImpl_SetDataFormat( LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df){ ICOM_THIS(SysMouseImpl,iface);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -