-
-
Save vincasmiliunas/895204 to your computer and use it in GitHub Desktop.
diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in | |
index d2cdc92..7fd804e 100644 | |
--- a/dlls/user32/Makefile.in | |
+++ b/dlls/user32/Makefile.in | |
@@ -1,7 +1,7 @@ | |
EXTRADEFS = -D_USER32_ -D_WINABLE_ | |
MODULE = user32.dll | |
IMPORTLIB = user32 | |
-IMPORTS = gdi32 version advapi32 | |
+IMPORTS = gdi32 version advapi32 dinput8 dinput dxguid | |
DELAYIMPORTS = imm32 | |
C_SRCS = \ | |
diff --git a/dlls/user32/input.c b/dlls/user32/input.c | |
index 06553a4..a8ed77e 100644 | |
--- a/dlls/user32/input.c | |
+++ b/dlls/user32/input.c | |
@@ -22,6 +22,15 @@ | |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
*/ | |
+/* | |
+ * Updated by Vincas Miliūnas 2011 | |
+ * Modififed by Reco 2009 | |
+ * patch is based on | |
+ * http://win2kgaming.site90.com/phpBB2/viewtopic.php?f=6&t=7 | |
+ * OldCigarettes Windows 2000 XP API Wrapper Pack | |
+ * Released under LGPL | |
+ */ | |
+ | |
#include "config.h" | |
#include "wine/port.h" | |
@@ -48,6 +57,383 @@ | |
#include "wine/server.h" | |
#include "wine/debug.h" | |
#include "wine/unicode.h" | |
+#include "dinput.h" | |
+ | |
+ | |
+static HANDLE hHeap = NULL; | |
+ | |
+typedef struct _myNode | |
+{ | |
+ DWORD data; | |
+ struct _myNode * next; | |
+} myNode; | |
+ | |
+typedef struct | |
+{ | |
+ myNode * head; | |
+ myNode * tail; | |
+ long length; | |
+ HANDLE lockMutex; | |
+} myList; | |
+ | |
+ | |
+__inline void GetLock(myList * l) | |
+{ | |
+ WaitForSingleObject(l->lockMutex, INFINITE); | |
+} | |
+ | |
+__inline void ReleaseLock(myList * l) | |
+{ | |
+ ReleaseMutex(l->lockMutex); | |
+} | |
+ | |
+ | |
+__inline void InitializeList(myList ** l) | |
+{ | |
+ *l = HeapAlloc(hHeap, 0, sizeof(myList)); | |
+ (*l)->head = NULL; | |
+ (*l)->tail = NULL; | |
+ (*l)->length = 0; | |
+ (*l)->lockMutex = CreateMutexA(NULL, FALSE, NULL); | |
+} | |
+ | |
+ | |
+__inline void PushFrontByAddr(myList * l, myNode * nouv) | |
+{ | |
+ if(!l->head) | |
+ l->tail = nouv; | |
+ | |
+ nouv->next = l->head; | |
+ l->head = nouv; | |
+ l->length++; | |
+} | |
+ | |
+__inline void PushBackByAddr(myList * l, myNode * nouv) | |
+{ | |
+ if(!l->head) | |
+ { | |
+ nouv->next = NULL; | |
+ l->tail = nouv; | |
+ l->head = nouv; | |
+ } | |
+ else | |
+ { | |
+ nouv->next = NULL; | |
+ l->tail->next = nouv; | |
+ l->tail = nouv; | |
+ } | |
+ l->length++; | |
+} | |
+ | |
+__inline void PushFrontByVal(myList * l, DWORD data) | |
+{ | |
+ myNode * nouv = NULL; | |
+ nouv = HeapAlloc(hHeap, 0, sizeof(myNode)); | |
+ nouv->next = l->head; | |
+ nouv->data = data; | |
+ | |
+ if(!l->head) | |
+ l->tail = nouv; | |
+ | |
+ l->head = nouv; | |
+ l->length++; | |
+} | |
+ | |
+__inline void PushBackByVal(myList * l, DWORD data) | |
+{ | |
+ myNode * nouv = NULL; | |
+ nouv = HeapAlloc(hHeap, 0, sizeof(myNode)); | |
+ nouv->data = data; | |
+ | |
+ if(!l->head) | |
+ { | |
+ nouv->next = NULL; | |
+ l->tail = nouv; | |
+ l->head = nouv; | |
+ } | |
+ else | |
+ { | |
+ nouv->next = NULL; | |
+ l->tail->next = nouv; | |
+ l->tail = nouv; | |
+ } | |
+ l->length++; | |
+} | |
+ | |
+__inline void RemoveNodeByVal(myList * l, DWORD data) | |
+{ | |
+ myNode * temp = NULL; | |
+ myNode * cour = NULL; | |
+ myNode ** prec = NULL; | |
+ | |
+ cour = l->head; | |
+ prec = &l->head; | |
+ | |
+ while(cour) | |
+ { | |
+ if(cour->data == data) | |
+ { | |
+ temp = cour->next; | |
+ | |
+ HeapFree(hHeap, 0, cour); | |
+ | |
+ *prec = temp; | |
+ cour = temp; | |
+ l->length--; | |
+ } | |
+ else | |
+ { | |
+ prec = &(cour->next); | |
+ cour = cour->next; | |
+ } | |
+ } | |
+} | |
+ | |
+__inline void RemoveNodeByAddr(myList * l, myNode * node) | |
+{ | |
+ myNode * temp = NULL; | |
+ myNode * cour = NULL; | |
+ myNode ** prec = NULL; | |
+ | |
+ cour = l->head; | |
+ prec = &l->head; | |
+ | |
+ while(cour) | |
+ { | |
+ if(cour == node) | |
+ { | |
+ temp = cour->next; | |
+ | |
+ HeapFree(hHeap, 0, cour); | |
+ | |
+ *prec = temp; | |
+ cour = temp; | |
+ l->length--; | |
+ } | |
+ else | |
+ { | |
+ prec = &(cour->next); | |
+ cour = cour->next; | |
+ } | |
+ } | |
+} | |
+ | |
+ | |
+__inline DWORD PopFrontAndFree(myList * l) | |
+{ | |
+ myNode * res = NULL; | |
+ DWORD data = 0; | |
+ | |
+ if(l->head && l->head == l->tail) | |
+ { | |
+ res = l->head; | |
+ l->head = NULL; | |
+ l->tail = NULL; | |
+ l->length = 0; | |
+ } | |
+ else if(l->head) | |
+ { | |
+ res = l->head; | |
+ l->head = res->next; | |
+ l->length--; | |
+ } | |
+ | |
+ //win2000 finds bug here!!!! | |
+ | |
+ if(res) { | |
+ data = res->data; | |
+ HeapFree(hHeap, 0, res); | |
+ } | |
+ | |
+ return data; | |
+} | |
+ | |
+ | |
+__inline void PopBackAndFree(myList * l) | |
+{ | |
+ myNode *res = NULL, *cour = NULL, *prec = NULL; | |
+ | |
+ if(l->head && l->head == l->tail) | |
+ { | |
+ res = l->head; | |
+ l->head = NULL; | |
+ l->tail = NULL; | |
+ l->length = 0; | |
+ } | |
+ else if(l->tail) | |
+ { | |
+ cour = l->head; | |
+ prec = l->head; | |
+ while(cour->next) | |
+ { | |
+ prec = cour; | |
+ cour = cour->next; | |
+ } | |
+ | |
+ res = l->tail; | |
+ l->tail = prec; | |
+ l->length--; | |
+ } | |
+ | |
+ if(res) | |
+ HeapFree(hHeap, 0, res); | |
+} | |
+ | |
+ | |
+ | |
+__inline myNode * PopFront(myList * l) | |
+{ | |
+ myNode * res = NULL; | |
+ | |
+ if(l->head && l->head == l->tail) | |
+ { | |
+ res = l->head; | |
+ l->head = NULL; | |
+ l->tail = NULL; | |
+ l->length = 0; | |
+ } | |
+ else if(l->head) | |
+ { | |
+ res = l->head; | |
+ l->head = res->next; | |
+ l->length--; | |
+ } | |
+ | |
+ return res; | |
+} | |
+ | |
+ | |
+__inline myNode * PopBack(myList * l) | |
+{ | |
+ myNode *res = NULL, *cour = NULL, *prec = NULL; | |
+ | |
+ if(l->head && l->head == l->tail) | |
+ { | |
+ res = l->head; | |
+ l->head = NULL; | |
+ l->tail = NULL; | |
+ l->length = 0; | |
+ } | |
+ else if(l->tail) | |
+ { | |
+ cour = l->head; | |
+ prec = l->head; | |
+ while(cour->next) | |
+ { | |
+ prec = cour; | |
+ cour = cour->next; | |
+ } | |
+ | |
+ res = l->tail; | |
+ prec->next = NULL; | |
+ l->tail = prec; | |
+ l->length--; | |
+ } | |
+ | |
+ return res; | |
+} | |
+ | |
+ | |
+__inline BOOL IsInListByVal(myList * l, DWORD data) | |
+{ | |
+ myNode * cour = NULL; | |
+ BOOL found = FALSE; | |
+ | |
+ cour = l->head; | |
+ while(cour && !found) | |
+ { | |
+ found = (cour->data == data); | |
+ cour = cour->next; | |
+ } | |
+ | |
+ return found; | |
+} | |
+ | |
+ | |
+__inline BOOL IsInListByAddr(myList * l, myNode * node) | |
+{ | |
+ myNode * cour = NULL; | |
+ BOOL found = FALSE; | |
+ | |
+ cour = l->head; | |
+ while(cour && !found) | |
+ { | |
+ found = (cour == node); | |
+ cour = cour->next; | |
+ } | |
+ | |
+ return found; | |
+} | |
+ | |
+ | |
+__inline void FreeList(myList ** l) | |
+{ | |
+ while((*l)->length) | |
+ PopFrontAndFree(*l); | |
+ | |
+ CloseHandle((*l)->lockMutex); | |
+ HeapFree(hHeap, 0, *l); | |
+ *l = NULL; | |
+} | |
+ | |
+/*Mode select*/ | |
+BOOL UseDirectInput = TRUE; | |
+ | |
+/*List of raw input data for each window*/ | |
+static myList * rawMouseInputWindowList = NULL; | |
+static myList * rawKeyboardInputWindowList = NULL; | |
+static myList * rawInputHandleList = NULL; | |
+ | |
+/*HOOK HANDLES*/ | |
+static HHOOK rawInputMouseHook = NULL; | |
+static HHOOK rawInputKeyboardHook = NULL; | |
+static BOOL mouseFirstRun = TRUE; | |
+ | |
+//X,Y coords to create relative movement of mouse from low level hook | |
+static LONG mouseHookLastX = 0, mouseHookLastY = 0; | |
+ | |
+/*DirectInput data*/ | |
+LPDIRECTINPUT8A lpdi = NULL; | |
+LPDIRECTINPUTDEVICE8A m_mouse = NULL; | |
+LPDIRECTINPUTDEVICE8A m_keyboard = NULL; | |
+HANDLE mouseInputEvent = NULL; | |
+ | |
+BOOL b_registered_mouse; | |
+BOOL b_registered_keyboard; | |
+RAWINPUTDEVICE rid_mouse; | |
+RAWINPUTDEVICE rid_keyboard; | |
+ | |
+//Only keep so many rawinput structures | |
+#define RAWINPUTHANDLETABLESIZE 32 | |
+ | |
+#define RIM_TYPEMOUSE 0 | |
+#define RIM_INPUT 0x00000000 | |
+#define MOUSE_MOVE_RELATIVE 0x00000000 | |
+#define MOUSE_MOVE_ABSOLUTE 0x00000001 | |
+#define MOUSE_VIRTUAL_DESKTOP 0x00000002 | |
+#define RI_MOUSE_LEFT_BUTTON_DOWN 0x0001 | |
+#define RI_MOUSE_LEFT_BUTTON_UP 0x0002 | |
+#define RI_MOUSE_RIGHT_BUTTON_DOWN 0x0004 | |
+#define RI_MOUSE_RIGHT_BUTTON_UP 0x0008 | |
+#define RI_MOUSE_MIDDLE_BUTTON_DOWN 0x0010 | |
+#define RI_MOUSE_MIDDLE_BUTTON_UP 0x0020 | |
+#define RI_MOUSE_BUTTON_1_DOWN RI_MOUSE_LEFT_BUTTON_DOWN | |
+#define RI_MOUSE_BUTTON_1_UP RI_MOUSE_LEFT_BUTTON_UP | |
+#define RI_MOUSE_BUTTON_2_DOWN RI_MOUSE_RIGHT_BUTTON_DOWN | |
+#define RI_MOUSE_BUTTON_2_UP RI_MOUSE_RIGHT_BUTTON_UP | |
+#define RI_MOUSE_BUTTON_3_DOWN RI_MOUSE_MIDDLE_BUTTON_DOWN | |
+#define RI_MOUSE_BUTTON_3_UP RI_MOUSE_MIDDLE_BUTTON_UP | |
+#define RI_MOUSE_BUTTON_4_DOWN 0x0040 | |
+#define RI_MOUSE_BUTTON_4_UP 0x0080 | |
+#define RI_MOUSE_BUTTON_5_DOWN 0x0100 | |
+#define RI_MOUSE_BUTTON_5_UP 0x0200 | |
+#define RI_MOUSE_WHEEL 0x0400 | |
+#define RIDEV_INPUTSINK 0x00000100 | |
+#define MOUSE_DEVICE_HANDLE 0x1337 | |
+#define RID_INPUT 0x10000003 | |
+#define RID_HEADER 0x10000005 | |
+#define RIDEV_REMOVE 0x00000001 | |
+#define RIDEV_CAPTUREMOUSE 0x00000200 | |
WINE_DEFAULT_DEBUG_CHANNEL(win); | |
WINE_DECLARE_DEBUG_CHANNEL(keyboard); | |
@@ -490,30 +876,439 @@ UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT | |
return 0; | |
} | |
+void SetRawInputMouseHeader(RAWINPUT *ri) { | |
+ ri->header.dwType = RIM_TYPEMOUSE; | |
+ ri->header.dwSize = sizeof(RAWINPUT); | |
+ ri->header.hDevice = MOUSE_DEVICE_HANDLE; | |
+ ri->header.wParam = RIM_INPUT; | |
+ return; | |
+} | |
+ | |
+RAWINPUT *GetDirectInputMouseData() { | |
+ static DIMOUSESTATE2 mouse_state; | |
+ static DIMOUSESTATE2 mouse_state_prev; | |
+ RAWINPUT *raw; | |
+ HRESULT hr; | |
+ int i; | |
+ | |
+ raw = (RAWINPUT*)HeapAlloc(hHeap, 0, sizeof(RAWINPUT)); | |
+ SetRawInputMouseHeader(raw); | |
+ | |
+ //Try to get input, and maybe reaquire input | |
+ hr = m_mouse->lpVtbl->GetDeviceState(m_mouse, sizeof(DIMOUSESTATE2), (LPVOID)&mouse_state); | |
+ if(FAILED(hr)) { | |
+ m_mouse->lpVtbl->Acquire(m_mouse); | |
+ while(hr == DIERR_INPUTLOST) { | |
+ hr = m_mouse->lpVtbl->Acquire(m_mouse); | |
+ } | |
+ if(FAILED(hr)) { | |
+ HeapFree(hHeap, 0, raw); | |
+ return NULL; | |
+ } | |
+ m_mouse->lpVtbl->GetDeviceState(m_mouse, sizeof(DIMOUSESTATE2), (LPVOID)&mouse_state); | |
+ } | |
+ | |
+ raw->data.mouse.usFlags = MOUSE_MOVE_RELATIVE; | |
+ raw->data.mouse.lLastX = mouse_state.lX; | |
+ raw->data.mouse.lLastY = mouse_state.lY; | |
+ raw->data.mouse.usButtonData = mouse_state.lZ & 0xFFFF; | |
+ raw->data.mouse.usButtonFlags = 0; | |
+ raw->data.mouse.ulRawButtons = 0; | |
+ | |
+ if(raw->data.mouse.usButtonData != 0) raw->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; | |
+ | |
+ for(i = 0; i < 8; i++) { | |
+ if(mouse_state.rgbButtons[i] & 0x80) { | |
+ raw->data.mouse.ulRawButtons |= 1<<i; | |
+ } | |
+ } | |
+ | |
+ if(mouse_state.rgbButtons[0] & 0x80 && !(mouse_state_prev.rgbButtons[0] & 0x80)) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_DOWN; | |
+ | |
+ if(!(mouse_state.rgbButtons[0] & 0x80) && mouse_state_prev.rgbButtons[0] & 0x80) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_UP; | |
+ | |
+ if(mouse_state.rgbButtons[1] & 0x80 && !(mouse_state_prev.rgbButtons[1] & 0x80)) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_DOWN; | |
+ | |
+ if(!(mouse_state.rgbButtons[1] & 0x80) && mouse_state_prev.rgbButtons[1] & 0x80) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_UP; | |
+ | |
+ if(mouse_state.rgbButtons[2] & 0x80 && !(mouse_state_prev.rgbButtons[2] & 0x80)) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_MIDDLE_BUTTON_DOWN; | |
+ | |
+ if(!(mouse_state.rgbButtons[2] & 0x80) && mouse_state_prev.rgbButtons[2] & 0x80) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_MIDDLE_BUTTON_UP; | |
+ | |
+ if(mouse_state.rgbButtons[3] & 0x80 && !(mouse_state_prev.rgbButtons[3] & 0x80)) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_4_DOWN; | |
+ | |
+ if(!(mouse_state.rgbButtons[3] & 0x80) && mouse_state_prev.rgbButtons[3] & 0x80) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_4_UP; | |
+ | |
+ if(mouse_state.rgbButtons[4] & 0x80 && !(mouse_state_prev.rgbButtons[4] & 0x80)) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_5_DOWN; | |
+ | |
+ if(!(mouse_state.rgbButtons[4] & 0x80) && mouse_state_prev.rgbButtons[4] & 0x80) | |
+ raw->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_5_UP; | |
+ | |
+ memcpy(&mouse_state_prev, &mouse_state, sizeof(DIMOUSESTATE2)); | |
+ | |
+ return raw; | |
+} | |
+ | |
+VOID AddRawInputToWindowList(RAWINPUT *ri, myList *windowList) { | |
+ myNode * cour = NULL; | |
+ GetLock(rawInputHandleList); | |
+ | |
+ //Remove old rawinputs | |
+ if(rawInputHandleList && rawInputHandleList->length > RAWINPUTHANDLETABLESIZE) | |
+ HeapFree(hHeap, 0, (RAWINPUT *)PopFrontAndFree(rawInputHandleList)); | |
+ | |
+ //Add this new RAWINPUT | |
+ PushBackByVal(rawInputHandleList, (DWORD)ri); | |
+ | |
+ GetLock(windowList); | |
+ for(cour = windowList->head; cour; cour = cour->next) { | |
+ PostMessageA((HWND)cour->data, WM_INPUT, RIM_INPUT, (LPARAM)ri); | |
+ } | |
+ ReleaseLock(windowList); | |
+ ReleaseLock(rawInputHandleList); | |
+ return; | |
+} | |
+ | |
+//Mouse and Keyboard seperate just to simplify things a bit | |
+DWORD WINAPI PollDirectInputMouse(PVOID data) { | |
+ RAWINPUT *raw; | |
+ for(;;) { | |
+ if(WaitForSingleObject(mouseInputEvent, 1000*2) != WAIT_ABANDONED) { | |
+ raw = GetDirectInputMouseData(); | |
+ if(raw) AddRawInputToWindowList(raw, rawMouseInputWindowList); | |
+ } | |
+ } | |
+ return 0; | |
+} | |
+ | |
+BOOL RegisterDirectInputMouse(PRAWINPUTDEVICE pRawInputDevices, HWND hWnd) { | |
+ HRESULT hr; | |
+ DWORD flags; | |
+ | |
+ //Try to map these flags to DirectX | |
+ flags = 0; | |
+ if(pRawInputDevices->dwFlags & RIDEV_INPUTSINK) flags |= DISCL_BACKGROUND; | |
+ else flags |= DISCL_FOREGROUND; | |
+ flags |= DISCL_NONEXCLUSIVE; | |
+ | |
+ //Init DirectInput if nessecary | |
+ if (lpdi == NULL && FAILED(DirectInput8Create(GetModuleHandleA(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void**)&lpdi, NULL))) { | |
+ ERR("user32: Failed to create DirectInput interface\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ //Init MouseDevice if nessecary | |
+ if (m_mouse == NULL && FAILED(lpdi->lpVtbl->CreateDevice(lpdi, &GUID_SysMouse, &m_mouse, NULL))) { | |
+ ERR("user32: Failed to create DirectInput mouse device\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ //Make friendly with this hWnd | |
+ if (FAILED(m_mouse->lpVtbl->SetCooperativeLevel(m_mouse, hWnd, flags))) { | |
+ ERR("user32: Failed to set cooperative level on DirectInput mouse device\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ if (FAILED(m_mouse->lpVtbl->SetDataFormat(m_mouse, &c_dfDIMouse2))) { | |
+ ERR("user32: Failed to set data format on DirectInput mouse device\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ if(!mouseInputEvent) { | |
+ HANDLE handle; | |
+ | |
+ mouseInputEvent = CreateEventA(NULL, FALSE, FALSE, NULL); | |
+ if(!mouseInputEvent) { | |
+ ERR("user32: Failed to create event for DirectInput mouse\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ handle = CreateThread(NULL, 0, PollDirectInputMouse, NULL, 0, NULL); | |
+ if(!handle) { | |
+ ERR("user32: Failed to create polling thread for DirectInput mouse\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ if(!SetThreadAffinityMask(handle, 1)) { | |
+ ERR("user32: Failed to set thread affinity mask for the DirectInput mouse polling thread\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ } | |
+ | |
+ //Must be NOT be acquired to SetEventNotification | |
+ m_mouse->lpVtbl->Unacquire(m_mouse); | |
+ if(FAILED(m_mouse->lpVtbl->SetEventNotification(m_mouse, mouseInputEvent))) { | |
+ ERR("user32: Failed to SetEventNotification for DirectInput mouse\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+//SetWindowsHookEx WH_MOUSE_LL handler | |
+LRESULT CALLBACK myLowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { | |
+ static ULONG ulRawButtons = 0; | |
+ RAWMOUSE *rm = NULL; | |
+ RAWINPUT *ri = NULL; | |
+ MSLLHOOKSTRUCT * hs = (MSLLHOOKSTRUCT*)lParam; | |
+ | |
+ if(nCode == HC_ACTION) { //Should always be true | |
+ ri = (RAWINPUT*)HeapAlloc(hHeap, 0, sizeof(RAWINPUT)); | |
+ if(ri) { | |
+ SetRawInputMouseHeader(ri); | |
+ | |
+ rm = &ri->data.mouse; | |
+ if(mouseFirstRun) { //first time around give the absolute position | |
+ rm->usFlags = MOUSE_MOVE_ABSOLUTE; | |
+ rm->lLastX = hs->pt.x; | |
+ rm->lLastY = hs->pt.y; | |
+ } else { | |
+ rm->usFlags = MOUSE_MOVE_RELATIVE; | |
+ if(hs->flags & LLMHF_INJECTED) { | |
+ rm->lLastX = 0; | |
+ rm->lLastY = 0; | |
+ } else { | |
+ rm->lLastX = (LONG)hs->pt.x - mouseHookLastX; | |
+ rm->lLastY = (LONG)hs->pt.y - mouseHookLastY; | |
+ } | |
+ } | |
+ | |
+ mouseHookLastX = hs->pt.x; | |
+ mouseHookLastY = hs->pt.y; | |
+ | |
+ rm->ulButtons = 0; | |
+ rm->usButtonData = 0; | |
+ rm->usButtonFlags = 0; | |
+ rm->ulExtraInformation = 0; | |
+ | |
+ //note ulRawButtons is static and we keep track of the state of the buttons this way | |
+ switch(wParam) | |
+ { | |
+ case WM_LBUTTONDOWN: | |
+ rm->usButtonFlags |= RI_MOUSE_LEFT_BUTTON_DOWN; | |
+ ulRawButtons |= 0x00000001; | |
+ break; | |
+ | |
+ case WM_LBUTTONUP: | |
+ rm->usButtonFlags |= RI_MOUSE_LEFT_BUTTON_UP; | |
+ ulRawButtons &= ~0x00000001; | |
+ break; | |
+ | |
+ case WM_RBUTTONDOWN: | |
+ rm->usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_DOWN; | |
+ ulRawButtons |= 0x00000002; | |
+ break; | |
+ | |
+ case WM_RBUTTONUP: | |
+ rm->usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_UP; | |
+ ulRawButtons &= ~0x00000002; | |
+ break; | |
+ | |
+ case WM_MBUTTONDOWN: | |
+ rm->usButtonFlags |= RI_MOUSE_MIDDLE_BUTTON_DOWN; | |
+ ulRawButtons |= 0x00000004; | |
+ break; | |
+ | |
+ case WM_MBUTTONUP: | |
+ rm->usButtonFlags |= RI_MOUSE_MIDDLE_BUTTON_UP; | |
+ ulRawButtons &= ~0x00000004; | |
+ break; | |
+ | |
+ case WM_MOUSEWHEEL: | |
+ rm->usButtonFlags |= RI_MOUSE_WHEEL; | |
+ rm->usButtonData = HIWORD(hs->mouseData); | |
+ break; | |
+ | |
+ case WM_XBUTTONDOWN: | |
+ if(HIWORD(hs->mouseData) == XBUTTON1) rm->usButtonFlags |= RI_MOUSE_BUTTON_4_DOWN; | |
+ else if(HIWORD(hs->mouseData) == XBUTTON2) rm->usButtonFlags |= RI_MOUSE_BUTTON_5_DOWN; | |
+ ulRawButtons |= (1 << (HIWORD(hs->mouseData) + 2)); | |
+ break; | |
+ | |
+ case WM_XBUTTONUP: | |
+ if(HIWORD(hs->mouseData) == XBUTTON1) rm->usButtonFlags |= RI_MOUSE_BUTTON_4_UP; | |
+ else if(HIWORD(hs->mouseData) == XBUTTON2) rm->usButtonFlags |= RI_MOUSE_BUTTON_5_UP; | |
+ ulRawButtons &= ~(1 << (HIWORD(hs->mouseData) + 2)); | |
+ break; | |
+ } | |
+ rm->ulRawButtons = ulRawButtons; | |
+ | |
+ if(!mouseFirstRun) { | |
+ AddRawInputToWindowList(ri, rawMouseInputWindowList); | |
+ } else { | |
+ mouseFirstRun = FALSE; | |
+ } | |
+ } | |
+ } | |
+ | |
+ return CallNextHookEx(rawInputMouseHook, nCode, wParam, lParam); | |
+} | |
+ | |
+VOID DeRegisterDirectInputMouse() { | |
+ m_mouse->lpVtbl->Unacquire(m_mouse); | |
+ m_mouse->lpVtbl->SetEventNotification(m_mouse, NULL); | |
+} | |
/****************************************************************** | |
* RegisterRawInputDevices (USER32.@) | |
*/ | |
-BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) | |
-{ | |
- FIXME("(pRawInputDevices=%p, uiNumDevices=%d, cbSize=%d) stub!\n", pRawInputDevices, uiNumDevices, cbSize); | |
+BOOL WINAPI RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) { | |
+ int i; | |
+ HWND hWnd; | |
+ | |
+ hHeap = GetProcessHeap(); | |
+ if(!rawMouseInputWindowList) InitializeList(&rawMouseInputWindowList); | |
+ if(!rawKeyboardInputWindowList) InitializeList(&rawKeyboardInputWindowList); | |
+ if(!rawInputHandleList) InitializeList(&rawInputHandleList); | |
+ | |
+ if(!pRawInputDevices || !uiNumDevices || !cbSize) { | |
+ SetLastError(ERROR_INVALID_PARAMETER); | |
+ return FALSE; | |
+ } | |
+ | |
+ for(i=0; i<uiNumDevices; i++) { | |
+ //Get the window handle if we need to | |
+ hWnd = pRawInputDevices[i].hwndTarget; | |
+ if(!hWnd) hWnd = GetFocus(); | |
+ if(!hWnd) hWnd = GetForegroundWindow(); //try this too | |
+ if(!hWnd) { | |
+ ERR("user32: couldn't get HWND for RegisterRawInputDevices\n"); | |
+ return FALSE; | |
+ } | |
+ | |
+ // Mouse input | |
+ if(pRawInputDevices[i].usUsagePage==1 && pRawInputDevices[i].usUsage==2) { //Mouse should match this | |
+ GetLock(rawMouseInputWindowList); | |
+ if(!(pRawInputDevices[i].dwFlags & RIDEV_REMOVE)) { | |
+ //Add | |
+ TRACE("user32: Adding a RAWINPUT mouse\n"); | |
+ | |
+ if(pRawInputDevices[i].dwFlags & RIDEV_CAPTUREMOUSE) | |
+ SetCapture(hWnd); | |
+ //Add the hWnd to the list | |
+ if(!IsInListByVal(rawMouseInputWindowList, (DWORD)hWnd)) | |
+ PushFrontByVal(rawMouseInputWindowList, (DWORD)hWnd); | |
+ | |
+ //If not getting low level data yet activate | |
+ if(UseDirectInput) { | |
+ if(!RegisterDirectInputMouse(&pRawInputDevices[i], hWnd)) | |
+ ERR("user32: Could not register DirectInput mouse\n"); | |
+ } else if(!rawInputMouseHook) { | |
+ rawInputMouseHook = SetWindowsHookExA(WH_MOUSE_LL, myLowLevelMouseProc, GetModuleHandleA("user32.dll"), 0); | |
+ if(!rawInputMouseHook) | |
+ ERR("user32: Could not SetWindowsHookEx WH_MOUSE_LL LastError=0x%X\n", GetLastError()); | |
+ } | |
+ //Save this structure to return with GetRegisteredRawInputDevices | |
+ b_registered_mouse = TRUE; | |
+ memcpy(&rid_mouse, &pRawInputDevices[i], sizeof(RAWINPUTDEVICE)); | |
+ } else { | |
+ //Remove | |
+ TRACE("user32: Removing a RAWINPUT mouse\n"); | |
+ | |
+ if(pRawInputDevices[i].hwndTarget) { | |
+ //This actually is not allowed | |
+ RemoveNodeByVal(rawMouseInputWindowList, (DWORD)pRawInputDevices[i].hwndTarget); | |
+ } else { | |
+ //Remove dem all! | |
+ while(rawMouseInputWindowList->length) | |
+ PopFrontAndFree(rawMouseInputWindowList); | |
+ } | |
+ | |
+ ReleaseCapture(); | |
+ | |
+ if(rawMouseInputWindowList->length==0) { | |
+ if(UseDirectInput) { | |
+ DeRegisterDirectInputMouse(); | |
+ } else if(rawInputMouseHook) { | |
+ UnhookWindowsHookEx(rawInputMouseHook); | |
+ rawInputMouseHook = NULL; | |
+ } | |
+ } | |
+ | |
+ b_registered_mouse = FALSE; | |
+ } | |
+ ReleaseLock(rawMouseInputWindowList); | |
+ } | |
+ | |
+ } | |
return TRUE; | |
} | |
- | |
/****************************************************************** | |
* GetRawInputData (USER32.@) | |
*/ | |
-UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) | |
-{ | |
- FIXME("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", | |
- hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); | |
+UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) { | |
+ UINT res = 0; | |
+ RAWINPUT *ri = (RAWINPUT*)hRawInput; | |
+ | |
+ if(cbSizeHeader != sizeof(RAWINPUTHEADER)) { | |
+ ERR("user32: sizeof(RAWINPUTHEADER) does not match expected\n"); | |
+ } | |
+ | |
+ GetLock(rawInputHandleList); | |
+ | |
+ //Ain't in the list no more | |
+ if(!hRawInput || !IsInListByVal(rawInputHandleList, (DWORD)hRawInput)) { | |
+ ReleaseLock(rawInputHandleList); | |
+ return ((UINT)-1); | |
+ } | |
+ | |
+ if(!pData) { | |
+ switch(uiCommand) { | |
+ case RID_INPUT: | |
+ *pcbSize = sizeof(RAWINPUT); | |
+ res = 0; | |
+ break; | |
+ | |
+ case RID_HEADER: | |
+ *pcbSize = sizeof(RAWINPUTHEADER); | |
+ res = 0; | |
+ break; | |
+ | |
+ default: | |
+ *pcbSize = 0; | |
+ res = (UINT)-1; | |
+ } | |
+ } else { | |
+ switch(uiCommand) { | |
+ case RID_INPUT: | |
+ if(*pcbSize >= sizeof(RAWINPUT)) { | |
+ res = *pcbSize; | |
+ RtlCopyMemory(pData, ri, sizeof(RAWINPUT)); | |
+ } else { | |
+ res = (UINT)-1; | |
+ } | |
+ break; | |
+ | |
+ case RID_HEADER: | |
+ if(*pcbSize >= sizeof(RAWINPUTHEADER)) { | |
+ res = *pcbSize; | |
+ RtlCopyMemory(pData, &ri->header, sizeof(RAWINPUTHEADER)); | |
+ } else { | |
+ res = (UINT)-1; | |
+ } | |
+ break; | |
+ | |
+ default: | |
+ res = (UINT)-1; | |
+ } | |
+ } | |
- return 0; | |
+ ReleaseLock(rawInputHandleList); | |
+ return res; | |
} | |
- | |
/****************************************************************** | |
* GetRawInputBuffer (USER32.@) | |
*/ | |
@@ -550,11 +1345,36 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, | |
/****************************************************************** | |
* GetRegisteredRawInputDevices (USER32.@) | |
*/ | |
-UINT WINAPI GetRegisteredRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize) | |
-{ | |
- FIXME("(pRawInputDevices=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDevices, puiNumDevices, cbSize); | |
- | |
- return 0; | |
+UINT WINAPI GetRegisteredRawInputDevices( | |
+ PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize) { | |
+ UINT nd; | |
+ if(cbSize != sizeof(RAWINPUTDEVICE)) { | |
+ ERR("user32: GetRegisteredRawInputDevices expected structure size %d got %d\n", | |
+ sizeof(RAWINPUTDEVICE), cbSize); | |
+ } | |
+ | |
+ //Since we only can the keyboard and mouse there should only ever be two | |
+ //devices. This will just return whatever structure they were registered | |
+ //with in this application. If you register more than once, you get the last. | |
+ nd = (b_registered_mouse?1:0) + (b_registered_keyboard?1:0); | |
+ | |
+ if(nd > *puiNumDevices || !pRawInputDevices) { | |
+ SetLastError(ERROR_INSUFFICIENT_BUFFER); | |
+ *puiNumDevices = nd; | |
+ return -1; | |
+ } | |
+ | |
+ if(b_registered_mouse) { | |
+ memcpy(pRawInputDevices, &rid_mouse, sizeof(RAWINPUTDEVICE)); | |
+ pRawInputDevices = (PRAWINPUTDEVICE)((PBYTE)pRawInputDevices + cbSize); | |
+ } | |
+ | |
+ if(b_registered_keyboard) { | |
+ memcpy(pRawInputDevices, &rid_keyboard, sizeof(RAWINPUTDEVICE)); | |
+ } | |
+ | |
+ *puiNumDevices = nd; | |
+ return nd; | |
} | |
diff --git a/include/winuser.h b/include/winuser.h | |
index a8b2c93..393939d 100644 | |
--- a/include/winuser.h | |
+++ b/include/winuser.h | |
@@ -491,8 +491,8 @@ typedef struct tagRAWMOUSE { | |
struct { | |
USHORT usButtonFlags; | |
USHORT usButtonData; | |
- } DUMMYSTRUCTNAME; | |
- } DUMMYUNIONNAME; | |
+ }; | |
+ }; | |
ULONG ulRawButtons; | |
LONG lLastX; | |
LONG lLastY; |
This patch works for version 0.7.1.1 WoT?
@stankz The patch is for WINE, not for WoT. Also read the comment above - https://gist.github.com/895204#gistcomment-71400 or use WoTFLIX.
[SOLVED]
It needs to start this command before compile:
$ ./tools/make_requests
Do not use this patch, as stated above, there is a better alternative version - http://dl.dropbox.com/u/6901628/raw3.patch.
Current wine from git.
I have these errors with raw3.patch:
gcc-4.2 -m32 -c -I. -I. -I../include -I../include -D__WINESRC__ -Wall -pipe -fno-strict-aliasing -Wdeclaration-after-statement -Wempty-body -Wstrict-prototypes -Wwrite-strings -fno-omit-frame-pointer -Wpointer-arith -I/tmp/Wineskin/include/freetype2 -I/tmp/Wineskin/include -I/tmp/Wineskin/include -arch i386 -m32 -O2 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk -mmacosx-version-min=10.7 -I/tmp/Wineskin/include -o raw_input.o raw_input.c
raw_input.c:137: warning: ‘struct raw_input_device_registration’ declared inside parameter list
raw_input.c:137: warning: its scope is only this definition or declaration, which is probably not what you want
raw_input.c: In function ‘register_raw_input_device’:
raw_input.c:146: error: dereferencing pointer to incomplete type
raw_input.c:147: error: ‘RAW_INPUT_DEVICE_FLAG_PAGEONLY’ undeclared (first use in this function)
raw_input.c:147: error: (Each undeclared identifier is reported only once
raw_input.c:147: error: for each function it appears in.)
raw_input.c:148: error: dereferencing pointer to incomplete type
raw_input.c:150: error: dereferencing pointer to incomplete type
raw_input.c:151: error: dereferencing pointer to incomplete type
raw_input.c:154: error: dereferencing pointer to incomplete type
raw_input.c:154: error: ‘RAW_INPUT_DEVICE_FLAG_REMOVE’ undeclared (first use in this function)
raw_input.c:162: error: dereferencing pointer to incomplete type
raw_input.c:163: error: dereferencing pointer to incomplete type
raw_input.c:167: error: dereferencing pointer to incomplete type
raw_input.c:171: error: dereferencing pointer to incomplete type
raw_input.c:172: error: dereferencing pointer to incomplete type
raw_input.c:173: error: dereferencing pointer to incomplete type
raw_input.c:174: error: dereferencing pointer to incomplete type
raw_input.c: In function ‘find_registered_usage’:
raw_input.c:254: error: ‘RAW_INPUT_DEVICE_FLAG_EXCLUDE’ undeclared (first use in this function)
raw_input.c:257: error: ‘RAW_INPUT_DEVICE_FLAG_PAGEONLY’ undeclared (first use in this function)
raw_input.c: In function ‘is_nolegacy_set_for_raw_input_mouse’:
raw_input.c:451: error: ‘RAW_INPUT_DEVICE_FLAG_NOLEGACY’ undeclared (first use in this function)
raw_input.c: In function ‘is_nolegacy_set_for_raw_input_keyboard’:
raw_input.c:458: error: ‘RAW_INPUT_DEVICE_FLAG_NOLEGACY’ undeclared (first use in this function)
raw_input.c: At top level:
raw_input.c:477: warning: ‘struct get_raw_input_device_list_reply’ declared inside parameter list
raw_input.c:477: warning: ‘struct get_raw_input_device_list_request’ declared inside parameter list
raw_input.c: In function ‘req_get_raw_input_device_list’:
raw_input.c:482: error: dereferencing pointer to incomplete type
raw_input.c:483: error: dereferencing pointer to incomplete type
raw_input.c:483: error: dereferencing pointer to incomplete type
raw_input.c:486: error: dereferencing pointer to incomplete type
raw_input.c:500: error: dereferencing pointer to incomplete type
raw_input.c: At top level:
raw_input.c:511: warning: ‘struct get_raw_input_device_info_reply’ declared inside parameter list
raw_input.c:511: warning: ‘struct get_raw_input_device_info_request’ declared inside parameter list
raw_input.c: In function ‘req_get_raw_input_device_info’:
raw_input.c:519: error: dereferencing pointer to incomplete type
raw_input.c:523: error: dereferencing pointer to incomplete type
raw_input.c:527: error: dereferencing pointer to incomplete type
raw_input.c:531: error: dereferencing pointer to incomplete type
raw_input.c:536: error: dereferencing pointer to incomplete type
raw_input.c:542: error: dereferencing pointer to incomplete type
raw_input.c:545: error: dereferencing pointer to incomplete type
raw_input.c:546: error: dereferencing pointer to incomplete type
raw_input.c:546: error: dereferencing pointer to incomplete type
raw_input.c: At top level:
raw_input.c:569: warning: ‘struct get_registered_raw_input_devices_reply’ declared inside parameter list
raw_input.c:569: warning: ‘struct get_registered_raw_input_devices_request’ declared inside parameter list
raw_input.c: In function ‘req_get_registered_raw_input_devices’:
raw_input.c:575: error: dereferencing pointer to incomplete type
raw_input.c:576: error: dereferencing pointer to incomplete type
raw_input.c:576: error: dereferencing pointer to incomplete type
raw_input.c:579: error: dereferencing pointer to incomplete type
raw_input.c: At top level:
raw_input.c:605: warning: ‘struct register_raw_input_devices_reply’ declared inside parameter list
raw_input.c:605: warning: ‘struct register_raw_input_devices_request’ declared inside parameter list
raw_input.c: In function ‘req_register_raw_input_devices’:
raw_input.c:610: error: dereferencing pointer to incomplete type
raw_input.c:611: error: invalid use of undefined type ‘struct raw_input_device_registration’
raw_input.c:611: error: dereferencing pointer to incomplete type
raw_input.c: At top level:
raw_input.c:615: warning: ‘struct get_raw_input_data_reply’ declared inside parameter list
raw_input.c:615: warning: ‘struct get_raw_input_data_request’ declared inside parameter list
raw_input.c: In function ‘req_get_raw_input_data’:
raw_input.c:618: error: dereferencing pointer to incomplete type
raw_input.c:620: error: dereferencing pointer to incomplete type
raw_input.c:629: error: dereferencing pointer to incomplete type
raw_input.c:630: error: dereferencing pointer to incomplete type
raw_input.c:631: error: dereferencing pointer to incomplete type
raw_input.c:632: error: dereferencing pointer to incomplete type
raw_input.c:633: error: dereferencing pointer to incomplete type
raw_input.c:634: error: dereferencing pointer to incomplete type
raw_input.c:635: error: dereferencing pointer to incomplete type
raw_input.c:636: error: dereferencing pointer to incomplete type
raw_input.c:643: error: dereferencing pointer to incomplete type
raw_input.c:646: error: dereferencing pointer to incomplete type
raw_input.c:652: error: dereferencing pointer to incomplete type
raw_input.c:660: error: dereferencing pointer to incomplete type
raw_input.c:662: error: dereferencing pointer to incomplete type
raw_input.c:662: error: dereferencing pointer to incomplete type
raw_input.c:664: error: dereferencing pointer to incomplete type
raw_input.c: At top level:
raw_input.c:669: warning: ‘struct get_raw_input_buffer_reply’ declared inside parameter list
raw_input.c:669: warning: ‘struct get_raw_input_buffer_request’ declared inside parameter list
raw_input.c: In function ‘req_get_raw_input_buffer’:
raw_input.c:676: error: dereferencing pointer to incomplete type
raw_input.c:679: error: dereferencing pointer to incomplete type
raw_input.c:680: error: dereferencing pointer to incomplete type
raw_input.c:690: error: dereferencing pointer to incomplete type
raw_input.c:713: error: dereferencing pointer to incomplete type
raw_input.c:714: error: dereferencing pointer to incomplete type
raw_input.c:716: error: dereferencing pointer to incomplete type
raw_input.c:733: error: dereferencing pointer to incomplete type
raw_input.c:738: error: dereferencing pointer to incomplete type
raw_input.c:744: error: dereferencing pointer to incomplete type
make[1]: *** [raw_input.o] Error 1
make[1]: *** Waiting for unfinished jobs....
@pomozoff Yes, you DO need to read the linked instructions in the second sentence.
@vincasmiliunas - Do you have a version of this that would work with a more recent version of wine, like 1.5.x?
761 //Remove
762 TRACE("user32: Removing a RAWINPUT mouse\n");
+ if (UseDirectInput && m_mouse == NULL) {
+ RegisterDirectInputMouse(&pRawInputDevices[i], hWnd);
+ }
if(pRawInputDevices[i].hwndTarget) {
//This actually is not allowed
RemoveNodeByVal(rawMouseInputWindowList, (DWORD)pRawInputDevices[i].hwndTarget);
} else {
It will be crash on DeRegisterDirectInputMouse().
Since somebody emailed me about this patch, I'll make an update.
Do not use this patch, as stated above, there is a better alternative version - http://dl.dropbox.com/u/6901628/raw3.patch . You can find instructions how to apply it in the "How to get the latest WINE's git working" comment - http://appdb.winehq.org/objectManager.php?sClass=version&iId=22521 .