Leaked source code of windows server 2003
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.

284 lines
8.4 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: capture.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * History:
  7. * 08-Nov-1990 DavidPe Created.
  8. * 01-Feb-1991 MikeKe Added Revalidation code
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. /***************************************************************************\
  13. * xxxSetCapture (API)
  14. *
  15. * This function sets the capture window for the current queue.
  16. *
  17. * History:
  18. * 08-Nov-1990 DavidPe Created.
  19. \***************************************************************************/
  20. PWND xxxSetCapture(
  21. PWND pwnd)
  22. {
  23. PQ pq;
  24. PWND pwndCaptureOld;
  25. HWND hwndCaptureOld;
  26. PTHREADINFO ptiCurrent = PtiCurrent();
  27. pq = (PQ)PtiCurrent()->pq;
  28. /*
  29. * If the capture is locked, bail
  30. */
  31. if (pq->QF_flags & QF_CAPTURELOCKED) {
  32. RIPMSG2(RIP_WARNING, "xxxSetCapture(%#p): Capture is locked. pq:%#p", pwnd, pq);
  33. return NULL;
  34. }
  35. /*
  36. * Don't allow the app to set capture to a window
  37. * from another queue.
  38. */
  39. if ((pwnd != NULL) && GETPTI(pwnd)->pq != pq)
  40. return NULL;
  41. /*
  42. * If full screen capture don't allow any other capture
  43. */
  44. if (gspwndScreenCapture)
  45. return NULL;
  46. pwndCaptureOld = pq->spwndCapture;
  47. hwndCaptureOld = HW(pwndCaptureOld);
  48. xxxCapture(ptiCurrent, pwnd, CLIENT_CAPTURE);
  49. if (hwndCaptureOld != NULL) {
  50. if (RevalidateHwnd(hwndCaptureOld))
  51. return pwndCaptureOld;
  52. }
  53. return NULL;
  54. }
  55. /***************************************************************************\
  56. * xxxReleaseCapture (API)
  57. *
  58. * This function release the capture for the current queue.
  59. *
  60. * History:
  61. * 08-Nov-1990 DavidPe Created.
  62. * 16-May-1991 MikeKe Changed to return BOOL
  63. \***************************************************************************/
  64. BOOL xxxReleaseCapture(VOID)
  65. {
  66. PTHREADINFO ptiCurrent = PtiCurrent();
  67. /*
  68. * If the capture is locked, bail
  69. */
  70. if (ptiCurrent->pq->QF_flags & QF_CAPTURELOCKED) {
  71. RIPMSG0(RIP_WARNING, "xxxReleaseCapture: Capture is locked");
  72. return FALSE;
  73. }
  74. /*
  75. * If we're releasing the capture from a window during tracking,
  76. * cancel tracking first.
  77. */
  78. if (ptiCurrent->pmsd != NULL) {
  79. /*
  80. * Only remove the tracking rectangle if it's
  81. * been made visible.
  82. */
  83. if (ptiCurrent->TIF_flags & TIF_TRACKRECTVISIBLE) {
  84. bSetDevDragRect(gpDispInfo->hDev, NULL, NULL);
  85. if (!(ptiCurrent->pmsd->fDragFullWindows))
  86. xxxDrawDragRect(ptiCurrent->pmsd, NULL, DDR_ENDCANCEL);
  87. ptiCurrent->TIF_flags &= ~(TIF_TRACKRECTVISIBLE | TIF_MOVESIZETRACKING);
  88. }
  89. }
  90. xxxCapture(ptiCurrent, NULL, NO_CAP_CLIENT);
  91. return TRUE;
  92. }
  93. /***************************************************************************\
  94. * xxxCapture
  95. *
  96. * This is the workhorse routine of capture setting and releasing.
  97. *
  98. * History:
  99. * 13-Nov-1990 DavidPe Created.
  100. \***************************************************************************/
  101. VOID xxxCapture(
  102. PTHREADINFO pti,
  103. PWND pwnd,
  104. UINT code)
  105. {
  106. CheckLock(pwnd);
  107. UserAssert(IsWinEventNotifyDeferredOK());
  108. if ((gspwndScreenCapture == NULL) ||
  109. (code == FULLSCREEN_CAPTURE) ||
  110. ((pwnd == NULL) && (code == NO_CAP_CLIENT) && (pti->pq != GETPTI(gspwndScreenCapture)->pq))) {
  111. PQ pq;
  112. PWND pwndCaptureOld = NULL;
  113. if (code == FULLSCREEN_CAPTURE) {
  114. if (pwnd) {
  115. Lock(&gspwndScreenCapture, pwnd);
  116. /*
  117. * We're going full screen so clear the mouse owner
  118. */
  119. Unlock(&gspwndMouseOwner);
  120. } else {
  121. Unlock(&gspwndScreenCapture);
  122. }
  123. }
  124. /*
  125. * Internal capture works like Win 3.1 capture unlike the NT capture
  126. * which can be lost if the user clicks down on another application
  127. */
  128. if (code == CLIENT_CAPTURE_INTERNAL) {
  129. Lock(&gspwndInternalCapture, pwnd);
  130. code = CLIENT_CAPTURE;
  131. }
  132. /*
  133. * Free the internal capture if the app (thread) that did the internal
  134. * capture is freeing the capture.
  135. */
  136. if ((code == NO_CAP_CLIENT) &&
  137. gspwndInternalCapture &&
  138. (pti == GETPTI(gspwndInternalCapture))) {
  139. Unlock(&gspwndInternalCapture);
  140. }
  141. if ((pq = pti->pq) != NULL) {
  142. PDESKTOP pdesk = pti->rpdesk;
  143. #if DBG
  144. if (pq->QF_flags & QF_CAPTURELOCKED) {
  145. RIPMSG1(RIP_WARNING, "pq %p already has QF_CAPTURELOCKED", pq);
  146. }
  147. #endif
  148. /*
  149. * If someone is tracking mouse events in the client area and
  150. * we're setting or releasing an internal capture mode (!= CLIENT_CAPTURE),
  151. * then cancel tracking -- because we're either taking or relinquishing
  152. * control over the mouse.
  153. */
  154. if ((pdesk->dwDTFlags & DF_TRACKMOUSEEVENT)
  155. && (pdesk->htEx == HTCLIENT)
  156. && ((pdesk->spwndTrack == pwnd)
  157. && (code != CLIENT_CAPTURE)
  158. || ((pdesk->spwndTrack == pq->spwndCapture)
  159. && (pq->codeCapture != CLIENT_CAPTURE)))) {
  160. BEGINATOMICCHECK();
  161. xxxCancelMouseMoveTracking(pdesk->dwDTFlags, pdesk->spwndTrack,
  162. pdesk->htEx, DF_TRACKMOUSEEVENT);
  163. ENDATOMICCHECK();
  164. }
  165. pwndCaptureOld = pq->spwndCapture;
  166. LockCaptureWindow(pq, pwnd);
  167. pq->codeCapture = code;
  168. } else {
  169. /*
  170. * A thread without a queue?
  171. */
  172. UserAssert(pti->pq != NULL);
  173. }
  174. /*
  175. * If there was a capture window and we're releasing it, post
  176. * a WM_MOUSEMOVE to the window we're over so they can know about
  177. * the current mouse position.
  178. * Defer WinEvent notifications to protect pwndCaptureOld
  179. */
  180. DeferWinEventNotify();
  181. if (pwnd == NULL && pwndCaptureOld != NULL) {
  182. #ifdef REDIRECTION
  183. if (!IsGlobalHooked(pti, WHF_FROM_WH(WH_HITTEST)))
  184. #endif
  185. zzzSetFMouseMoved();
  186. }
  187. if (pwndCaptureOld) {
  188. zzzWindowEvent(EVENT_SYSTEM_CAPTUREEND, pwndCaptureOld, OBJID_WINDOW,
  189. INDEXID_CONTAINER, WEF_USEPWNDTHREAD);
  190. }
  191. if (pwnd) {
  192. zzzWindowEvent(EVENT_SYSTEM_CAPTURESTART, pwnd, OBJID_WINDOW,
  193. INDEXID_CONTAINER, WEF_USEPWNDTHREAD);
  194. }
  195. /*
  196. * New for win95 - send WM_CAPTURECHANGED.
  197. *
  198. * The FNID_DELETED_BIT is set in xxxFreeWindow which means we
  199. * DON'T want to send the message.
  200. */
  201. if (pwndCaptureOld &&
  202. TestWF(pwndCaptureOld, WFWIN40COMPAT) &&
  203. !(pwndCaptureOld->fnid & FNID_DELETED_BIT)) {
  204. TL tlpwnd;
  205. /*
  206. * If we are in menu mode and just set capture,
  207. * don't let them take it from us during this
  208. * callback.
  209. */
  210. if ((pti->pMenuState != NULL) && (pwnd != NULL)) {
  211. pq->QF_flags |= QF_CAPTURELOCKED;
  212. }
  213. ThreadLockAlways(pwndCaptureOld, &tlpwnd);
  214. zzzEndDeferWinEventNotify();
  215. xxxSendMessageCallback(pwndCaptureOld,
  216. WM_CAPTURECHANGED,
  217. FALSE,
  218. (LPARAM)HW(pwnd),
  219. NULL,
  220. 0,
  221. FALSE);
  222. /* The thread's queue may have changed during the callback,
  223. * so we need to refresh the local. Bug #377795
  224. */
  225. pq = pti->pq;
  226. UserAssert(pq != NULL);
  227. ThreadUnlock(&tlpwnd);
  228. /*
  229. * Release the temporary lock, if any
  230. */
  231. pq->QF_flags &= ~QF_CAPTURELOCKED;
  232. } else {
  233. zzzEndDeferWinEventNotify();
  234. }
  235. }
  236. }