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.

494 lines
10 KiB

  1. /*=========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: winwatch.c
  6. * Content: 16-bit window watch code
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 20-jun-95 craige split out of DCIMAN WINWATCH.C, tweaked
  11. * 22-jun-95 craige re-worked for clipper stuff
  12. * 02-jul-95 craige comment out clipper notify stuff
  13. *
  14. ***************************************************************************/
  15. #define _INC_DCIDDI
  16. #include "ddraw16.h"
  17. #undef _INC_DCIDDI
  18. #ifdef CLIPPER_NOTIFY
  19. static LPWINWATCH lpWWList;
  20. static HHOOK hNextCallWndProc;
  21. static BOOL bUnHook;
  22. long FAR PASCAL _loadds CallWndProcHook(int hc, WPARAM wParam, LPARAM lParam);
  23. extern HRGN FAR PASCAL InquireVisRgn(HDC hdc);
  24. extern DWORD FAR PASCAL GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA prd);
  25. /*
  26. * doNotify
  27. */
  28. void doNotify(LPWINWATCH pww, DWORD code)
  29. {
  30. if( pww->lpCallback )
  31. {
  32. extern void DDAPI DD32_ClippingNotify( LPVOID, DWORD );
  33. DD32_ClippingNotify( pww->self32, code );
  34. }
  35. } /* doNotify */
  36. /*
  37. * DD16_WWOpen
  38. */
  39. void DDAPI DD16_WWOpen( LPWINWATCH ptr )
  40. {
  41. if( lpWWList == NULL )
  42. {
  43. DPF( 2, "Setting Windows Hook" );
  44. hNextCallWndProc = (HHOOK) SetWindowsHook( WH_CALLWNDPROC,
  45. (HOOKPROC) CallWndProcHook );
  46. }
  47. lpWWList = ptr;
  48. } /* DD16_WWOpen */
  49. /*
  50. * DD16_WWClose
  51. */
  52. void DDAPI DD16_WWClose( LPWINWATCH pww, LPWINWATCH newlist )
  53. {
  54. if( pww->prd16 != NULL )
  55. {
  56. LocalFree( (HLOCAL) pww->prd16 );
  57. pww->prd16 = NULL;
  58. }
  59. if( newlist == NULL )
  60. {
  61. DPF( 3, "Flagging to Unhook" );
  62. bUnHook = TRUE;
  63. }
  64. lpWWList = newlist;
  65. } /* DD16_WWClose */
  66. /*
  67. * DD16_WWNotifyInit
  68. */
  69. void DDAPI DD16_WWNotifyInit(
  70. LPWINWATCH pww,
  71. LPCLIPPERCALLBACK lpcallback,
  72. LPVOID param )
  73. {
  74. doNotify( pww, WINWATCHNOTIFY_STOP );
  75. pww->lpCallback = lpcallback;
  76. pww->lpContext = param;
  77. doNotify( pww, WINWATCHNOTIFY_START );
  78. doNotify( pww, WINWATCHNOTIFY_CHANGED );
  79. pww->fNotify = FALSE;
  80. } /* DD16_WWNotifyInit */
  81. /*
  82. * getWindowRegionData
  83. */
  84. static DWORD getWindowRegionData( HWND hwnd, DWORD size, RGNDATA NEAR * prd )
  85. {
  86. HDC hdc;
  87. DWORD dw;
  88. hdc = GetDCEx( hwnd, NULL, DCX_USESTYLE | DCX_CACHE );
  89. dw = GetRegionData( InquireVisRgn( hdc ), size, prd );
  90. ReleaseDC( hwnd, hdc );
  91. return dw;
  92. } /* getWindowRegionData */
  93. /*
  94. * DD16_WWGetClipList
  95. */
  96. DWORD DDAPI DD16_WWGetClipList(
  97. LPWINWATCH pww,
  98. LPRECT prect,
  99. DWORD rdsize,
  100. LPRGNDATA prd )
  101. {
  102. DWORD dw;
  103. DWORD size;
  104. /*
  105. * we have to see if the intersect rect has changed.
  106. */
  107. if( prect )
  108. {
  109. if( !EqualRect(prect, &pww->rect) )
  110. {
  111. pww->fDirty = TRUE;
  112. }
  113. }
  114. else
  115. {
  116. if( !IsRectEmpty( &pww->rect ) )
  117. {
  118. pww->fDirty = TRUE;
  119. }
  120. }
  121. /*
  122. * if we are not dirty just return the saved RGNDATA
  123. */
  124. if( !pww->fDirty && pww->prd16 )
  125. {
  126. size = sizeof( *prd ) + (WORD) pww->prd16->rdh.nRgnSize;
  127. if( prd == NULL )
  128. {
  129. return size;
  130. }
  131. if( rdsize < size )
  132. {
  133. size = rdsize;
  134. }
  135. _fmemcpy( prd, pww->prd16, (UINT) size );
  136. return size;
  137. }
  138. /*
  139. * get the RGNDATA, growing the memory if we have to
  140. */
  141. dw = getWindowRegionData( (HWND) pww->hWnd, pww->dwRDSize, pww->prd16 );
  142. if( dw > pww->dwRDSize )
  143. {
  144. DPF( 2, "GetClipList: growing RGNDATA memory from %ld to %ld",pww->dwRDSize, dw);
  145. if( pww->prd16 != NULL )
  146. {
  147. LocalFree((HLOCAL)pww->prd16);
  148. }
  149. /*
  150. * allocate new space plus some slop
  151. */
  152. pww->dwRDSize = dw + 8*sizeof(RECTL);
  153. pww->prd16 = (RGNDATA NEAR *) LocalAlloc(LPTR, (UINT)pww->dwRDSize);
  154. if( pww->prd16 == NULL )
  155. {
  156. goto error;
  157. }
  158. dw = getWindowRegionData( (HWND) pww->hWnd, pww->dwRDSize, pww->prd16 );
  159. if( dw > pww->dwRDSize )
  160. {
  161. goto error;
  162. }
  163. }
  164. /*
  165. * now intersect the region with the passed rect
  166. */
  167. if( prect )
  168. {
  169. pww->rect = *prect;
  170. DPF( 2, "GetClipList: intersect with [%d %d %d %d]", *prect);
  171. ClipRgnToRect( (HWND) pww->hWnd, prect, pww->prd16 );
  172. }
  173. else
  174. {
  175. SetRectEmpty( &pww->rect );
  176. }
  177. pww->fDirty = FALSE;
  178. size = sizeof( *prd ) + (WORD) pww->prd16->rdh.nRgnSize;
  179. if( prd == NULL )
  180. {
  181. return size;
  182. }
  183. if( rdsize < size )
  184. {
  185. size = rdsize;
  186. }
  187. _fmemcpy( prd, pww->prd16, (UINT) size );
  188. return size;
  189. error:
  190. pww->dwRDSize = 0;
  191. return 0;
  192. } /* DD16_WWGetClipList */
  193. /****************************************************************************
  194. * *
  195. * ROUTINES TO HANDLE NOTIFICATION MESSAGES FOLLOW *
  196. * *
  197. ****************************************************************************/
  198. /*
  199. * handleWindowDestroyed
  200. */
  201. static void handleWindowDestroy( HWND hwnd )
  202. {
  203. LPWINWATCH pww;
  204. DPF( 2, "*** handleWindowDestroy: hwnd=%08lx", hwnd );
  205. again:
  206. for( pww=lpWWList; pww; pww=pww->next16 )
  207. {
  208. if( (hwnd == NULL) || ((HWND)pww->hWnd == hwnd) )
  209. {
  210. extern void DDAPI DD32_WWClose( DWORD );
  211. doNotify( pww, WINWATCHNOTIFY_DESTROY );
  212. DD32_WWClose( (DWORD) pww->self32 );
  213. goto again;
  214. }
  215. }
  216. } /* handleWindowDestroy */
  217. /*
  218. * handleWindowPosChanged
  219. */
  220. static void handleWindowPosChanged( HWND hwnd )
  221. {
  222. LPWINWATCH pww;
  223. LPWINWATCH next;
  224. RECT rect;
  225. RECT rectT;
  226. DPF( 20, "*** handleWindowPosChanged: hwnd=%08lx", hwnd );
  227. /*
  228. * get the screen rect that changed
  229. */
  230. GetWindowRect( hwnd, &rect );
  231. /*
  232. * send message to each notify routine
  233. */
  234. pww = lpWWList;
  235. while( pww != NULL )
  236. {
  237. next = pww->next16;
  238. GetWindowRect((HWND)pww->hWnd, &rectT);
  239. if( IntersectRect( &rectT, &rectT, &rect ) )
  240. {
  241. pww->fNotify = TRUE;
  242. pww->fDirty = TRUE;
  243. }
  244. if( pww->fNotify && pww->lpCallback )
  245. {
  246. DPF( 20, "clip changed %04X [%d %d %d %d]", (HWND)pww->hWnd, rectT);
  247. doNotify( pww, WINWATCHNOTIFY_CHANGED );
  248. pww->fNotify = FALSE;
  249. }
  250. pww = next;
  251. }
  252. } /* handleWindowPosChanged */
  253. /*
  254. * sendChanging
  255. */
  256. static void sendChanging( LPRECT prect )
  257. {
  258. LPWINWATCH pww;
  259. LPWINWATCH next;
  260. RECT rectT;
  261. pww = lpWWList;
  262. while( pww != NULL )
  263. {
  264. next = pww->next16;
  265. GetWindowRect( (HWND)pww->hWnd, &rectT );
  266. if( IntersectRect(&rectT, &rectT, prect) )
  267. {
  268. pww->fDirty = TRUE;
  269. if( pww->lpCallback )
  270. {
  271. DPF( 20, "clip changing %04X [%d %d %d %d]", (HWND)pww->hWnd, rectT);
  272. doNotify( pww, WINWATCHNOTIFY_CHANGING );
  273. pww->fNotify = TRUE;
  274. pww->fDirty = TRUE;
  275. }
  276. }
  277. pww = next;
  278. }
  279. } /* sendChanging */
  280. /*
  281. * handleWindowPosChanging
  282. */
  283. static void handleWindowPosChanging( HWND hwnd, LPWINDOWPOS pwinpos )
  284. {
  285. RECT rect;
  286. RECT rect_win;
  287. int cx;
  288. int cy;
  289. /*
  290. * get the current screen rect.
  291. */
  292. DPF( 20, "*** handleWindowPosChanging: hwnd=%08lx", hwnd );
  293. GetWindowRect( hwnd, &rect_win);
  294. rect = rect_win;
  295. if( pwinpos == NULL )
  296. {
  297. sendChanging( &rect );
  298. return;
  299. }
  300. /*
  301. * compute the new rect
  302. */
  303. if( pwinpos->flags & SWP_NOSIZE )
  304. {
  305. cx = rect.right - rect.left;
  306. cy = rect.bottom - rect.top;
  307. }
  308. else
  309. {
  310. cx = pwinpos->cx;
  311. cy = pwinpos->cy;
  312. }
  313. if( !(pwinpos->flags & SWP_NOMOVE) )
  314. {
  315. rect.left = pwinpos->x;
  316. rect.top = pwinpos->y;
  317. if( GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD )
  318. {
  319. ClientToScreen(GetParent(hwnd), (LPPOINT)&rect);
  320. }
  321. }
  322. rect.right = rect.left + cx;
  323. rect.bottom = rect.top + cy;
  324. /*
  325. * only send changing if we are really changing... if the new
  326. * rect is the same as the old rect, then check if something else
  327. * interesting is happening...
  328. */
  329. if( EqualRect( &rect, &rect_win ) )
  330. {
  331. if( !(pwinpos->flags & SWP_NOZORDER) )
  332. {
  333. sendChanging(&rect);
  334. }
  335. if( pwinpos->flags & (SWP_SHOWWINDOW|SWP_HIDEWINDOW) )
  336. {
  337. sendChanging(&rect);
  338. }
  339. }
  340. else
  341. {
  342. sendChanging( &rect_win );
  343. sendChanging( &rect );
  344. }
  345. } /* handleWindowPosChanging */
  346. /*
  347. * checkScreenLock
  348. */
  349. static void checkScreenLock( void )
  350. {
  351. static BOOL bScreenLocked;
  352. BOOL is_locked;
  353. HDC hdc;
  354. RECT rect;
  355. hdc = GetDC(NULL);
  356. is_locked = (GetClipBox(hdc, &rect) == NULLREGION);
  357. ReleaseDC(NULL, hdc);
  358. if( is_locked != bScreenLocked )
  359. {
  360. /*
  361. * pretend the desktop window has moved, this will cause
  362. * all WINWATCH handles to be set to dirty, and also be notified.
  363. */
  364. handleWindowPosChanging( GetDesktopWindow(), NULL );
  365. handleWindowPosChanged( GetDesktopWindow() );
  366. bScreenLocked = is_locked;
  367. }
  368. } /* checkScreenLock */
  369. /*
  370. * CallWndProcHook
  371. */
  372. long FAR PASCAL _loadds CallWndProcHook( int hc, WPARAM wParam, LPARAM lParam )
  373. {
  374. /* reversed MSG minus time and pt */
  375. typedef struct
  376. {
  377. LONG lParam;
  378. WORD wParam;
  379. WORD message;
  380. HWND hwnd;
  381. } MSGR, FAR *LPMSGR;
  382. LPMSGR lpmsg;
  383. LPWINDOWPOS lpwinpos;
  384. long rc;
  385. if( hc == HC_ACTION )
  386. {
  387. lpmsg = (MSGR FAR *)lParam;
  388. switch( lpmsg->message )
  389. {
  390. case WM_DESTROY:
  391. handleWindowDestroy( lpmsg->hwnd );
  392. break;
  393. case WM_WINDOWPOSCHANGING:
  394. lpwinpos = (LPWINDOWPOS) lpmsg->lParam;
  395. handleWindowPosChanging( lpwinpos->hwnd, lpwinpos );
  396. break;
  397. case WM_WINDOWPOSCHANGED:
  398. lpwinpos = (LPWINDOWPOS) lpmsg->lParam;
  399. handleWindowPosChanged( lpwinpos->hwnd );
  400. break;
  401. case WM_EXITSIZEMOVE:
  402. checkScreenLock();
  403. break;
  404. case WM_ENTERSIZEMOVE:
  405. checkScreenLock();
  406. break;
  407. }
  408. }
  409. rc = DefHookProc(hc, wParam, lParam, &(HOOKPROC)hNextCallWndProc);
  410. if( bUnHook )
  411. {
  412. DPF( 2, "Unhooking WindowsHook" );
  413. UnhookWindowsHook( WH_CALLWNDPROC, (HOOKPROC)CallWndProcHook );
  414. bUnHook = FALSE;
  415. }
  416. return rc;
  417. } /* CallWndProcHook */
  418. #endif