Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

327 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. mouse.cpp
  5. Abstract:
  6. This module contains all the Low Level Mouse functions.
  7. Author:
  8. Michael Tsang (MikeTs) 01-Jun-2000
  9. Environment:
  10. User mode
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #ifdef MOUSE_THREAD
  15. //
  16. // Global data
  17. //
  18. HHOOK ghMouseHook = NULL;
  19. TCHAR gtszMouseClass[] = TEXT("MouseClass");
  20. /*++
  21. @doc INTERNAL
  22. @func unsigned | MouseThread | Low Level Mouse thread.
  23. @parm IN PVOID | param | Points to the thread structure.
  24. @rvalue Always returns 0.
  25. --*/
  26. unsigned __stdcall
  27. MouseThread(
  28. IN PVOID param
  29. )
  30. {
  31. TRACEPROC("MouseThread", 2)
  32. WNDCLASSEX wc;
  33. TRACEENTER(("(pThread=%p)\n", param));
  34. // Bump our priority so we can service mouse events ASAP.
  35. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  36. memset(&wc, 0, sizeof(wc));
  37. wc.cbSize = sizeof(wc);
  38. wc.lpfnWndProc = MouseWndProc;
  39. wc.hInstance = ghMod;
  40. wc.lpszClassName = gtszMouseClass;
  41. RegisterClassEx(&wc);
  42. while (!(gdwfTabSrv & TSF_TERMINATE))
  43. {
  44. if (SwitchThreadToInputDesktop((PTSTHREAD)param))
  45. {
  46. BOOL fImpersonate;
  47. fImpersonate = ImpersonateCurrentUser();
  48. CoInitialize(NULL);
  49. DoLowLevelMouse((PTSTHREAD)param);
  50. CoUninitialize();
  51. if (fImpersonate)
  52. {
  53. RevertToSelf();
  54. }
  55. }
  56. else
  57. {
  58. TABSRVERR(("Failed to set current desktop.\n"));
  59. break;
  60. }
  61. }
  62. TRACEINFO(1, ("Mouse thread exiting...\n"));
  63. TRACEEXIT(("=0\n"));
  64. return 0;
  65. } //MouseThread
  66. /*++
  67. @doc INTERNAL
  68. @func VOID | DoLowLevelMouse | Do low level mouse instead.
  69. @parm IN PTSTHREAD | pThread | Points to the thread structure.
  70. @rvalue None.
  71. --*/
  72. VOID
  73. DoLowLevelMouse(
  74. IN PTSTHREAD pThread
  75. )
  76. {
  77. TRACEPROC("DoLowLevelMouse", 2)
  78. TRACEENTER(("()\n"));
  79. TRACEASSERT(ghwndMouse == NULL);
  80. ghwndMouse = CreateWindow(gtszMouseClass,
  81. gtszMouseClass,
  82. WS_POPUP,
  83. CW_USEDEFAULT,
  84. 0,
  85. CW_USEDEFAULT,
  86. 0,
  87. NULL,
  88. NULL,
  89. ghMod,
  90. 0);
  91. if (ghwndMouse != NULL)
  92. {
  93. pThread->pvSDTParam = ghwndMouse;
  94. ghMouseHook = SetWindowsHookEx(WH_MOUSE_LL,
  95. LowLevelMouseProc,
  96. ghMod,
  97. 0);
  98. if (ghMouseHook != NULL)
  99. {
  100. MSG msg;
  101. DWORD rcWait;
  102. while (GetMessage(&msg, NULL, 0, 0))
  103. {
  104. TranslateMessage(&msg);
  105. DispatchMessage(&msg);
  106. }
  107. UnhookWindowsHookEx(ghMouseHook);
  108. ghMouseHook = NULL;
  109. }
  110. else
  111. {
  112. DestroyWindow(ghwndMouse);
  113. TABSRVERR(("Failed to hook low level mouse events.\n"));
  114. }
  115. ghwndMouse = NULL;
  116. }
  117. else
  118. {
  119. TABSRVERR(("Failed to create mouse window.\n"));
  120. }
  121. TRACEEXIT(("!\n"));
  122. return;
  123. } //DoLowLevelMouse
  124. /*++
  125. @doc EXTERNAL
  126. @func LRESULT | LowLevelMouseProc | Low level mouse hook procedure.
  127. @parm IN int | nCode | Specifies a code to determine how to process
  128. the message.
  129. @parm IN WPARAM | wParam | Specifies hte mouse message.
  130. @parm IN LPARAM | lParam | Points to the MSLLHOOKSTRUCT structure.
  131. @rvalue Returns non-zero if to prevent others to process.
  132. --*/
  133. LRESULT CALLBACK
  134. LowLevelMouseProc(
  135. IN int nCode,
  136. IN WPARAM wParam,
  137. IN LPARAM lParam
  138. )
  139. {
  140. TRACEPROC("LowLevelMouseProc", 5)
  141. LRESULT rc = 0;
  142. PMSLLHOOKSTRUCT pHookStruct = (PMSLLHOOKSTRUCT)lParam;
  143. TRACEENTER(("(nCode=%x,wParam=%s,lParam=%x)\n",
  144. nCode, LookupName(wParam, WMMsgNames), lParam));
  145. if ((nCode >= 0) && !(pHookStruct->flags & LLMHF_INJECTED))
  146. {
  147. WORD wCurrentButtons;
  148. gInput.mi.dx = SCREEN_TO_NORMAL_X(pHookStruct->pt.x);
  149. gInput.mi.dy = SCREEN_TO_NORMAL_Y(pHookStruct->pt.y);
  150. wCurrentButtons = gwLastButtons;
  151. switch (wParam)
  152. {
  153. case WM_LBUTTONDOWN:
  154. wCurrentButtons |= TIP_SWITCH;
  155. break;
  156. case WM_LBUTTONUP:
  157. wCurrentButtons &= ~TIP_SWITCH;
  158. break;
  159. case WM_RBUTTONDOWN:
  160. wCurrentButtons |= BARREL_SWITCH;
  161. break;
  162. case WM_RBUTTONUP:
  163. wCurrentButtons &= ~BARREL_SWITCH;
  164. break;
  165. }
  166. rc = ProcessMouseEvent((WORD)gInput.mi.dx,
  167. (WORD)gInput.mi.dy,
  168. wCurrentButtons,
  169. pHookStruct->time,
  170. TRUE);
  171. gwLastButtons = wCurrentButtons;
  172. if (rc == 0)
  173. {
  174. rc = CallNextHookEx(ghMouseHook, nCode, wParam, lParam);
  175. }
  176. }
  177. else
  178. {
  179. rc = CallNextHookEx(ghMouseHook, nCode, wParam, lParam);
  180. }
  181. TRACEEXIT(("=%x\n", rc));
  182. return rc;
  183. } //LowLevelMouseProc
  184. /*++
  185. @doc EXTERNAL
  186. @func LRESULT | MouseWndProc | Mouse window proc.
  187. @parm IN HWND | hwnd | Window handle.
  188. @parm IN UINT | uiMsg | Window message.
  189. @parm IN WPARAM | wParam | Param 1.
  190. @parm IN LPARAM | lParam | Param 2.
  191. @rvalue Return code is message specific.
  192. --*/
  193. LRESULT CALLBACK
  194. MouseWndProc(
  195. IN HWND hwnd,
  196. IN UINT uiMsg,
  197. IN WPARAM wParam,
  198. IN LPARAM lParam
  199. )
  200. {
  201. TRACEPROC("MouseWndProc", 5)
  202. LRESULT rc = 0;
  203. TRACEENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
  204. hwnd, LookupName(uiMsg, WMMsgNames), wParam, lParam));
  205. switch (uiMsg)
  206. {
  207. case WM_CREATE:
  208. giButtonsSwapped = GetSystemMetrics(SM_SWAPBUTTON);
  209. break;
  210. case WM_SETTINGCHANGE:
  211. if (wParam == SPI_SETMOUSEBUTTONSWAP)
  212. {
  213. giButtonsSwapped = GetSystemMetrics(SM_SWAPBUTTON);
  214. }
  215. break;
  216. case WM_TIMER:
  217. //
  218. // Press and hold expired, enter press and hold mode.
  219. //
  220. KillTimer(hwnd, wParam);
  221. if (gdwPenState == PENSTATE_PENDOWN)
  222. {
  223. PressHoldMode(TRUE);
  224. SetTimer(ghwndMouse,
  225. TIMERID_PRESSHOLD,
  226. gConfig.GestureSettings.iCancelPressHoldTime,
  227. NULL);
  228. }
  229. else if (gdwPenState == PENSTATE_PRESSHOLD)
  230. {
  231. TRACEINFO(3, ("Simulate a left-down on CancelPressHold timeout.\n"));
  232. gdwPenState = PENSTATE_NORMAL;
  233. SetPressHoldCursor(FALSE);
  234. gInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE |
  235. MOUSEEVENTF_MOVE |
  236. MOUSEEVENTF_VIRTUALDESK |
  237. SWAPBUTTONS(giButtonsSwapped,
  238. MOUSEEVENTF_LEFTDOWN,
  239. MOUSEEVENTF_RIGHTDOWN);
  240. gInput.mi.dx = glPenDownX;
  241. gInput.mi.dy = glPenDownY;
  242. SendInput(1, &gInput, sizeof(INPUT));
  243. }
  244. else if (gdwPenState == PENSTATE_LEFTUP_PENDING)
  245. {
  246. TRACEINFO(3, ("Simulate a left-up on timeout.\n"));
  247. gdwPenState = PENSTATE_NORMAL;
  248. gInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE |
  249. MOUSEEVENTF_MOVE |
  250. MOUSEEVENTF_VIRTUALDESK |
  251. SWAPBUTTONS(giButtonsSwapped,
  252. MOUSEEVENTF_LEFTUP,
  253. MOUSEEVENTF_RIGHTUP);
  254. gInput.mi.dx = glPenUpX;
  255. gInput.mi.dy = glPenUpY;
  256. SendInput(1, &gInput, sizeof(INPUT));
  257. }
  258. break;
  259. case WM_CLOSE:
  260. DestroyWindow(hwnd);
  261. PostQuitMessage(0);
  262. break;
  263. default:
  264. rc = DefWindowProc(hwnd, uiMsg, wParam, lParam);
  265. }
  266. TRACEEXIT(("=%x\n", rc));
  267. return rc;
  268. } //MouseWndProc
  269. #endif //ifdef MOUSE_THREAD