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.

386 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: icons.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains routines having to do with icons.
  7. *
  8. * History:
  9. * 11-14-90 DarrinM Created.
  10. * 13-Feb-1991 mikeke Added Revalidation code
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #define DX_GAP (SYSMET(CXMINSPACING) - SYSMET(CXMINIMIZED))
  15. #define DY_GAP (SYSMET(CYMINSPACING) - SYSMET(CYMINIMIZED))
  16. /***************************************************************************\
  17. * xxxArrangeIconicWindows
  18. *
  19. * Function to arrange all icons for a particular window. Does this by
  20. * Returns 0 if no icons or the height of one
  21. * icon row if there are any icons.
  22. *
  23. * History:
  24. * 11-14-90 darrinm Ported from Win 3.0 sources.
  25. * 4-17-91 mikehar Win31 Merge
  26. \***************************************************************************/
  27. UINT xxxArrangeIconicWindows(
  28. PWND pwnd)
  29. {
  30. PBWL pbwl;
  31. PSMWP psmwp;
  32. PWND pwndTest, pwndSort, pwndSwitch;
  33. HWND *phwnd, *phwndSort;
  34. CHECKPOINT *pcp, *pcpSort;
  35. POINT ptSort, ptSrc;
  36. WORD nIcons = 0;
  37. RECT rc;
  38. POINT ptMin;
  39. int xOrg, yOrg;
  40. int dx, dy;
  41. int dxSlot, dySlot;
  42. int cIconsPerPass, iIconPass;
  43. BOOL fHorizontal, fBreak;
  44. TL tlpwndTest;
  45. BOOL fHideMe;
  46. CheckLock(pwnd);
  47. /*
  48. * Create a window list of all children of pwnd
  49. */
  50. if ((pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL)) == NULL)
  51. return 0;
  52. fHideMe = IsTrayWindow(pwnd->spwndChild);
  53. //
  54. // Put these into local vars for efficiency (see ParkIcon())
  55. //
  56. dxSlot = SYSMET(CXMINSPACING);
  57. dySlot = SYSMET(CYMINSPACING);
  58. //
  59. // We need to adjust the client rectangle if the parent has scrollbars.
  60. //
  61. GetRealClientRect(pwnd, &rc, GRC_SCROLLS, NULL);
  62. /*
  63. * find all icons
  64. */
  65. pwndSwitch = RevalidateHwnd(ghwndSwitch);
  66. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  67. if (((pwndTest = RevalidateHwnd(*phwnd)) == NULL) ||
  68. !TestWF(pwndTest , WFVISIBLE) ||
  69. pwndTest == pwndSwitch ||
  70. (pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT,
  71. PROPF_INTERNAL)) == NULL) {
  72. *phwnd = NULL;
  73. continue;
  74. }
  75. if (!TestWF(pwndTest, WFMINIMIZED)) {
  76. pcp->fMinInitialized = FALSE;
  77. pcp->ptMin.x = pcp->ptMin.y = -1;
  78. *phwnd = NULL;
  79. continue;
  80. }
  81. /*
  82. * inc count of icons
  83. */
  84. nIcons++;
  85. /*
  86. * we will park in default position again...
  87. */
  88. pcp->fDragged = FALSE;
  89. /*
  90. * ensure the original position is up to date
  91. */
  92. pcp->ptMin.x = pwndTest->rcWindow.left;
  93. pcp->ptMin.y = pwndTest->rcWindow.top;
  94. _ScreenToClient(pwnd, &pcp->ptMin);
  95. // Slide into the nearest row or column
  96. switch (SYSMET(ARRANGE) & ~ARW_HIDE) {
  97. case ARW_TOPLEFT | ARW_RIGHT:
  98. case ARW_TOPRIGHT | ARW_LEFT:
  99. // Slide into top row
  100. pcp->ptMin.y += dySlot / 2;
  101. pcp->ptMin.y -= pcp->ptMin.y % dySlot;
  102. break;
  103. case ARW_TOPLEFT | ARW_DOWN:
  104. case ARW_BOTTOMLEFT | ARW_UP:
  105. // Slide into left column
  106. pcp->ptMin.x += dxSlot / 2;
  107. pcp->ptMin.x -= pcp->ptMin.x % dxSlot;
  108. break;
  109. case ARW_BOTTOMLEFT | ARW_RIGHT:
  110. case ARW_BOTTOMRIGHT | ARW_LEFT:
  111. // Slide into bottom row
  112. pcp->ptMin.y = rc.bottom - pcp->ptMin.y;
  113. pcp->ptMin.y += dySlot / 2;
  114. pcp->ptMin.y -= pcp->ptMin.y % dySlot;
  115. pcp->ptMin.y = rc.bottom - pcp->ptMin.y;
  116. break;
  117. case ARW_BOTTOMRIGHT | ARW_UP:
  118. case ARW_TOPRIGHT | ARW_DOWN:
  119. // Slide into right column
  120. pcp->ptMin.x = rc.right - pcp->ptMin.x;
  121. pcp->ptMin.x += dxSlot / 2;
  122. pcp->ptMin.x -= pcp->ptMin.x % dxSlot;
  123. pcp->ptMin.x = rc.right - pcp->ptMin.x;
  124. break;
  125. }
  126. }
  127. if (nIcons == 0) {
  128. /*
  129. * no icons were found... break out
  130. */
  131. FreeHwndList(pbwl);
  132. return 0;
  133. }
  134. if (fHideMe) {
  135. ptMin.x = WHERE_NOONE_CAN_SEE_ME;
  136. ptMin.y = WHERE_NOONE_CAN_SEE_ME;
  137. goto JustParkEm;
  138. }
  139. //
  140. // Get gravity && move vars
  141. //
  142. if (SYSMET(ARRANGE) & ARW_STARTRIGHT) {
  143. // Starting on right side
  144. ptMin.x = xOrg = rc.right - dxSlot;
  145. dx = -dxSlot;
  146. } else {
  147. // Starting on left
  148. ptMin.x = xOrg = rc.left + DX_GAP;
  149. dx = dxSlot;
  150. }
  151. if (SYSMET(ARRANGE) & ARW_STARTTOP) {
  152. // Starting on top
  153. ptMin.y = yOrg = rc.top + DY_GAP;
  154. dy = dySlot;
  155. } else {
  156. // Starting on bottom
  157. ptMin.y = yOrg = rc.bottom - dySlot;
  158. dy = -dySlot;
  159. }
  160. //
  161. // Get arrange dir
  162. //
  163. fHorizontal = ( (SYSMET(ARRANGE) & ARW_DOWN) ? FALSE : TRUE );
  164. iIconPass = fHorizontal ? (rc.right / dxSlot) : (rc.bottom / dySlot);
  165. cIconsPerPass = iIconPass = max(1, iIconPass);
  166. /*
  167. * insertion sort of windows by y, and by x within a row.
  168. */
  169. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  170. /*
  171. * Check for 0 (window was not icon) and
  172. * Check for invalid HWND (window has been destroyed)
  173. */
  174. if (*phwnd == NULL || (pwndTest = RevalidateHwnd(*phwnd)) == NULL)
  175. continue;
  176. pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT,
  177. PROPF_INTERNAL);
  178. ptSrc = pcp->ptMin;
  179. fBreak = FALSE;
  180. for (phwndSort = pbwl->rghwnd; phwndSort < phwnd; phwndSort++) {
  181. if (*phwndSort == NULL ||
  182. (pwndSort = RevalidateHwnd(*phwndSort)) == NULL)
  183. continue;
  184. pcpSort = (CHECKPOINT*)_GetProp(pwndSort, PROP_CHECKPOINT,
  185. PROPF_INTERNAL);
  186. ptSort = pcpSort->ptMin;
  187. //
  188. // Is this the position in which to sort this min window?
  189. //
  190. switch (SYSMET(ARRANGE) & ~ARW_HIDE) {
  191. case ARW_BOTTOMLEFT | ARW_RIGHT:
  192. // Lower left, moving horizontally
  193. if (((ptSort.y == ptSrc.y) && (ptSort.x > ptSrc.x)) ||
  194. (ptSort.y < ptSrc.y))
  195. fBreak = TRUE;
  196. break;
  197. case ARW_BOTTOMLEFT | ARW_UP:
  198. // Lower left, moving vertically
  199. if (((ptSort.x == ptSrc.x) && (ptSort.y < ptSrc.y)) ||
  200. (ptSort.x > ptSrc.x))
  201. fBreak = TRUE;
  202. break;
  203. case ARW_BOTTOMRIGHT | ARW_LEFT:
  204. // Lower right, moving horizontally
  205. if (((ptSort.y == ptSrc.y) && (ptSort.x < ptSrc.x)) ||
  206. (ptSort.y < ptSrc.y))
  207. fBreak = TRUE;
  208. break;
  209. case ARW_BOTTOMRIGHT | ARW_UP:
  210. // Lower right, moving vertically
  211. if (((ptSort.x == ptSrc.x) && (ptSort.y < ptSrc.y)) ||
  212. (ptSort.x < ptSrc.x))
  213. fBreak = TRUE;
  214. break;
  215. case ARW_TOPLEFT | ARW_RIGHT:
  216. // Top left, moving horizontally
  217. if (((ptSort.y == ptSrc.y) && (ptSort.x > ptSrc.x)) ||
  218. (ptSort.y > ptSrc.y))
  219. fBreak = TRUE;
  220. break;
  221. case ARW_TOPLEFT | ARW_DOWN:
  222. // Top left, moving vertically
  223. if (((ptSort.x == ptSrc.x) && (ptSort.y > ptSrc.y)) ||
  224. (ptSort.x > ptSrc.x))
  225. fBreak = TRUE;
  226. break;
  227. case ARW_TOPRIGHT | ARW_LEFT:
  228. // Top right, moving horizontally
  229. if (((ptSort.y == ptSrc.y) && (ptSort.x < ptSrc.x)) ||
  230. (ptSort.y > ptSrc.y))
  231. fBreak = TRUE;
  232. break;
  233. case ARW_TOPRIGHT | ARW_DOWN:
  234. // Top right, moving vertically
  235. if (((ptSort.x == ptSrc.x) && (ptSort.y > ptSrc.y)) ||
  236. (ptSort.x < ptSrc.x))
  237. fBreak = TRUE;
  238. break;
  239. }
  240. if (fBreak)
  241. break;
  242. }
  243. /*
  244. * insert the window at this position by sliding the rest up.
  245. * LATER IanJa, use hwnd intermediate variables, avoid PW() & HW()
  246. */
  247. while (phwndSort < phwnd) {
  248. pwndSort = PW(*phwndSort);
  249. *phwndSort = HW(pwndTest);
  250. pwndTest = pwndSort;
  251. phwndSort++;
  252. }
  253. /*
  254. * replace the window handle in the original position
  255. */
  256. *phwnd = HW(pwndTest);
  257. }
  258. //
  259. // Now park the icons.
  260. //
  261. JustParkEm:
  262. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  263. if (*phwnd == NULL || (pwndTest = RevalidateHwnd(*phwnd)) == NULL)
  264. continue;
  265. pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT,
  266. PROPF_INTERNAL);
  267. if (pcp != NULL) {
  268. pcp->fMinInitialized = TRUE;
  269. pcp->ptMin = ptMin;
  270. }
  271. if (fHideMe) {
  272. continue;
  273. }
  274. // Setup to process the next position
  275. if (--iIconPass <= 0) {
  276. // Need to setup next pass
  277. iIconPass = cIconsPerPass;
  278. if (fHorizontal) {
  279. ptMin.x = xOrg;
  280. ptMin.y += dy;
  281. } else {
  282. ptMin.x += dx;
  283. ptMin.y = yOrg;
  284. }
  285. } else {
  286. // Same pass
  287. if (fHorizontal)
  288. ptMin.x += dx;
  289. else
  290. ptMin.y += dy;
  291. }
  292. }
  293. psmwp = InternalBeginDeferWindowPos(2 * nIcons);
  294. if (psmwp == NULL)
  295. goto ParkExit;
  296. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  297. /*
  298. * Check for a NULL (window has gone away)
  299. */
  300. if (*phwnd == NULL || (pwndTest = RevalidateHwnd(*phwnd)) == NULL)
  301. continue;
  302. pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT,
  303. PROPF_INTERNAL);
  304. ThreadLockAlways(pwndTest, &tlpwndTest);
  305. psmwp = _DeferWindowPos(
  306. psmwp,
  307. pwndTest,
  308. NULL,
  309. pcp->ptMin.x,
  310. pcp->ptMin.y,
  311. SYSMET(CXMINIMIZED),
  312. SYSMET(CYMINIMIZED),
  313. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
  314. ThreadUnlock(&tlpwndTest);
  315. if (psmwp == NULL)
  316. break;
  317. }
  318. if (psmwp != NULL) {
  319. /*
  320. * Make the swp async so we don't hang waiting for hung apps.
  321. */
  322. xxxEndDeferWindowPosEx(psmwp, TRUE);
  323. }
  324. ParkExit:
  325. FreeHwndList(pbwl);
  326. return nIcons;
  327. }