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.

806 lines
24 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: shadow.c
  3. *
  4. * Copyright (c) 1985 - 2000, Microsoft Corporation
  5. *
  6. * Drop shadow support.
  7. *
  8. * History:
  9. * 04/12/2000 vadimg created
  10. * 02/12/2001 msadek added rounded rectangular shadow support
  11. * for rectangular windows
  12. * 05/08/2001 msadek rewrote the non rounded corners shadow algorithm
  13. * to work well with regional windows, correct visuall effect.
  14. \***************************************************************************/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. // shadow horizontal and veritcal offsets
  18. #define CX_SHADOW 5
  19. #define CY_SHADOW 5
  20. #define C_SHADOW CX_SHADOW
  21. // black as the shadow color
  22. #define RGBA_SHADOW 0x00FFFFFF
  23. // white as the transparent color
  24. #define RGBA_TRANSPARENT 0x00000000
  25. typedef struct tagSHADOW *PSHADOW;
  26. typedef struct tagSHADOW {
  27. PWND pwnd; // window we're shadowing
  28. PWND pwndShadow; // the shadow window we create
  29. PSHADOW pshadowNext; // link to the next shadow struct
  30. } SHADOW;
  31. PSHADOW gpshadowFirst;
  32. // Macro used to map gray scale shadow values to alpha blending scale.
  33. #define ALPHA(x) ((255 - (x)) << 24)
  34. #define ARGB(a, r, g, b) (((DWORD)a<<24)|((DWORD)r<<16)|((DWORD)g<<8)|b)
  35. // Gray scale values for the shadow grades
  36. #define GS01 255
  37. #define GS02 254
  38. #define GS03 253
  39. #define GS04 252
  40. #define GS05 250
  41. #define GS06 246
  42. #define GS07 245
  43. #define GS08 242
  44. #define GS09 241
  45. #define GS10 227
  46. #define GS11 217
  47. #define GS12 213
  48. #define GS13 212
  49. #define GS14 199
  50. #define GS15 180
  51. #define GS16 172
  52. #define GS17 171
  53. #define GS18 155
  54. #define GS19 144
  55. #define GS20 142
  56. // pre-computed alpha values for the shadow
  57. CONST BYTE grgShadow[C_SHADOW] = {
  58. GS04, GS09, GS13, GS17, GS20,
  59. };
  60. CONST ULONG TopRightLTR [CY_SHADOW][CX_SHADOW] = {
  61. ALPHA(GS08), ALPHA(GS06), ALPHA(GS05), ALPHA(GS03), ALPHA(GS02),
  62. ALPHA(GS11), ALPHA(GS10), ALPHA(GS09), ALPHA(GS05), ALPHA(GS02),
  63. ALPHA(GS15), ALPHA(GS14), ALPHA(GS10), ALPHA(GS07), ALPHA(GS03),
  64. ALPHA(GS18), ALPHA(GS15), ALPHA(GS11), ALPHA(GS08), ALPHA(GS03),
  65. ALPHA(GS19), ALPHA(GS16), ALPHA(GS12), ALPHA(GS09), ALPHA(GS04),
  66. };
  67. CONST ULONG RightLTR [CX_SHADOW] = {
  68. ALPHA(GS20), ALPHA(GS17), ALPHA(GS13), ALPHA(GS09), ALPHA(GS04),
  69. };
  70. CONST ULONG BottomRightLTR [CY_SHADOW][CX_SHADOW] = {
  71. ALPHA(GS18), ALPHA(GS15), ALPHA(GS11), ALPHA(GS08), ALPHA(GS03),
  72. ALPHA(GS15), ALPHA(GS14), ALPHA(GS10), ALPHA(GS07), ALPHA(GS03),
  73. ALPHA(GS11), ALPHA(GS10), ALPHA(GS09), ALPHA(GS05), ALPHA(GS02),
  74. ALPHA(GS08), ALPHA(GS06), ALPHA(GS05), ALPHA(GS03), ALPHA(GS02),
  75. ALPHA(GS03), ALPHA(GS03), ALPHA(GS02), ALPHA(GS02), ALPHA(GS01),
  76. };
  77. CONST ULONG Bottom [CY_SHADOW] = {
  78. ALPHA(GS20), ALPHA(GS17), ALPHA(GS13), ALPHA(GS09), ALPHA(GS04),
  79. };
  80. CONST ULONG BottomLeftLTR [CY_SHADOW][CX_SHADOW] = {
  81. ALPHA(GS08), ALPHA(GS11), ALPHA(GS15), ALPHA(GS18), ALPHA(GS19),
  82. ALPHA(GS06), ALPHA(GS10), ALPHA(GS14), ALPHA(GS15), ALPHA(GS16),
  83. ALPHA(GS05), ALPHA(GS09), ALPHA(GS10), ALPHA(GS11), ALPHA(GS12),
  84. ALPHA(GS03), ALPHA(GS05), ALPHA(GS07), ALPHA(GS08), ALPHA(GS09),
  85. ALPHA(GS02), ALPHA(GS02), ALPHA(GS03), ALPHA(GS03), ALPHA(GS04),
  86. };
  87. /***************************************************************************\
  88. * DrawWindowShadow
  89. *
  90. \***************************************************************************/
  91. BOOL DrawWindowShadow(PWND pwnd, HDC hdc, BOOL fRTL, BOOL fForceComplexRgn, PBOOL pfSimpleRgn)
  92. {
  93. HRGN hrgn1, hrgn2;
  94. RECT rc;
  95. HBRUSH hBrushShadow;
  96. BOOL bRet = FALSE;
  97. UserAssert(pfSimpleRgn != NULL);
  98. hrgn1 = GreCreateRectRgn(0, 0, 0, 0);
  99. hrgn2 = GreCreateRectRgn(0, 0, 0, 0);
  100. if (hrgn1 == NULL || hrgn2 == NULL) {
  101. goto Cleanup;
  102. }
  103. /*
  104. * Handle the case when the window is a rectangle or a regional window.
  105. */
  106. if (pwnd->hrgnClip == NULL || TestWF(pwnd, WFMAXFAKEREGIONAL)) {
  107. rc = pwnd->rcWindow;
  108. OffsetRect(&rc, -rc.left, -rc.top);
  109. GreSetRectRgn(hrgn1, 0, 0, rc.right, rc.bottom);
  110. *pfSimpleRgn = TRUE;
  111. } else {
  112. GreCombineRgn(hrgn1, pwnd->hrgnClip, NULL, RGN_COPY);
  113. GreOffsetRgn(hrgn1, -pwnd->rcWindow.left, -pwnd->rcWindow.top);
  114. *pfSimpleRgn = FALSE;
  115. }
  116. /*
  117. * Offset the window by the shadow offsets and fill the difference
  118. * with the shadow color. The result will be window's shadow.
  119. */
  120. GreCombineRgn(hrgn2, hrgn1, NULL, RGN_COPY);
  121. if (fRTL) {
  122. GreOffsetRgn(hrgn1, CX_SHADOW, 0);
  123. GreOffsetRgn(hrgn2, 0, CY_SHADOW);
  124. } else {
  125. GreOffsetRgn(hrgn2, CX_SHADOW, CY_SHADOW);
  126. }
  127. bRet = TRUE;
  128. if (!*pfSimpleRgn || fForceComplexRgn) {
  129. int i;
  130. BYTE gs;
  131. for (i = C_SHADOW ; i > 0; i--) {
  132. gs = grgShadow[i - 1];
  133. hBrushShadow = GreCreateSolidBrush(RGB(gs , gs , gs));
  134. if (hBrushShadow == NULL) {
  135. bRet = FALSE;
  136. goto Cleanup;
  137. }
  138. NtGdiFrameRgn(hdc, hrgn2, hBrushShadow, i, i);
  139. GreDeleteObject(hBrushShadow);
  140. }
  141. GreFillRgn(hdc, hrgn1, (HBRUSH)GreGetStockObject(BLACK_BRUSH));
  142. } else {
  143. GreCombineRgn(hrgn2, hrgn2, hrgn1, RGN_DIFF);
  144. GreFillRgn(hdc, hrgn2, (HBRUSH)GreGetStockObject(WHITE_BRUSH));
  145. }
  146. Cleanup:
  147. GreDeleteObject(hrgn1);
  148. GreDeleteObject(hrgn2);
  149. return bRet;
  150. }
  151. /***************************************************************************\
  152. * DrawTopLogicallyRightCorner
  153. *
  154. * Draw the shadow effect of the top, logically right (visually right for LTR, left for RTL window layout)
  155. * corner of a rounded rectangular shadow.
  156. *
  157. * History:
  158. * 02/12/2001 Mohamed Sadek [msadek] created
  159. \***************************************************************************/
  160. _inline void DrawTopLogicallyRightCorner(VOID* pBits, LONG cx, LONG cy, BOOL fRTL)
  161. {
  162. LONG i, j;
  163. ULONG* ppixel;
  164. if (fRTL) {
  165. for (i = CY_SHADOW; i < (2 * CY_SHADOW); i++) {
  166. for (j = 0; j < CX_SHADOW; j++) {
  167. ppixel = (ULONG*)pBits + ((cy - i - 1) * cx) + j;
  168. *ppixel = TopRightLTR[i - CY_SHADOW][CX_SHADOW - 1 - j];
  169. }
  170. }
  171. }
  172. else {
  173. for (i = CY_SHADOW; i < (2 * CY_SHADOW); i++) {
  174. for (j = 0; j < CX_SHADOW; j++) {
  175. ppixel = (ULONG*)pBits + ((cy - i) * cx) - CX_SHADOW + j;
  176. *ppixel = TopRightLTR[i - CY_SHADOW][j];
  177. }
  178. }
  179. }
  180. }
  181. /***************************************************************************\
  182. * DrawLogicallyRightSide
  183. *
  184. * Draw the shadow effect of the logically right (visually right for LTR, left for RTL window layout)
  185. * side of a rounded rectangular shadow.
  186. *
  187. * History:
  188. * 02/12/2001 Mohamed Sadek [msadek] created
  189. \***************************************************************************/
  190. _inline void DrawLogicallyRightSide(VOID* pBits, LONG cx, LONG cy, BOOL fRTL)
  191. {
  192. LONG i, j;
  193. ULONG* ppixel;
  194. if (fRTL) {
  195. for (i = (2 * CY_SHADOW); i < (cy - CY_SHADOW); i++) {
  196. for (j = 0; j < CX_SHADOW; j++) {
  197. ppixel = (ULONG*)pBits + (cx * ( cy - i -1)) + j;
  198. *ppixel = RightLTR[CX_SHADOW - 1 - j];
  199. }
  200. }
  201. } else {
  202. for (i = (2 * CY_SHADOW); i < (cy - CY_SHADOW); i++) {
  203. for (j = 0; j < CX_SHADOW; j++) {
  204. ppixel = (ULONG*)pBits + (cx * ( cy - i -1)) + (cx - CX_SHADOW) + j;
  205. *ppixel = RightLTR[j];
  206. }
  207. }
  208. }
  209. }
  210. /***************************************************************************\
  211. * DrawBottomLogicallyRightCorner
  212. *
  213. * Draw the shadow effect of the bottom logically right (visually right for LTR, left for RTL window layout)
  214. * side of a rounded rectangular shadow.
  215. *
  216. * History:
  217. * 02/12/2001 Mohamed Sadek [msadek] created
  218. \***************************************************************************/
  219. _inline void DrawBottomLogicallyRightCorner(VOID* pBits, LONG cx, BOOL fRTL)
  220. {
  221. LONG i, j;
  222. ULONG* ppixel;
  223. if (fRTL) {
  224. for (i = 0; i < CY_SHADOW; i++) {
  225. for (j = 0; j < CX_SHADOW; j++) {
  226. ppixel = (ULONG*)pBits + ((CY_SHADOW - i - 1) * cx) + j;
  227. *ppixel = BottomRightLTR[i][CX_SHADOW - 1 - j];
  228. }
  229. }
  230. } else {
  231. for (i = 0; i < CY_SHADOW; i++) {
  232. for (j = 0; j < CX_SHADOW; j++) {
  233. ppixel = (ULONG*)pBits + ((CY_SHADOW - i) * cx) - CX_SHADOW + j;
  234. *ppixel = BottomRightLTR[i][j];
  235. }
  236. }
  237. }
  238. }
  239. /***************************************************************************\
  240. * DrawBottomSide
  241. *
  242. * Draw the shadow effect of the bottom side of a rounded rectangular shadow.
  243. *
  244. * History:
  245. * 02/12/2001 Mohamed Sadek [msadek] created
  246. \***************************************************************************/
  247. _inline void DrawBottomSide(VOID* pBits, LONG cx, BOOL fRTL)
  248. {
  249. LONG i, j;
  250. ULONG* ppixel;
  251. if (fRTL) {
  252. for (i = 0; i < CY_SHADOW; i++) {
  253. for (j = CX_SHADOW; j < (cx - (2 * CX_SHADOW)); j++) {
  254. ppixel = (ULONG*)pBits + ((CY_SHADOW - i - 1) * cx) + j;
  255. *ppixel = Bottom[i];
  256. }
  257. }
  258. } else {
  259. for (i = 0; i < CY_SHADOW; i++) {
  260. for (j = (2 * CX_SHADOW); j < (cx - CX_SHADOW); j++) {
  261. ppixel = (ULONG*)pBits + ((CY_SHADOW - i - 1) * cx) + j;
  262. *ppixel = Bottom[i];
  263. }
  264. }
  265. }
  266. }
  267. /***************************************************************************\
  268. * DrawBottomLogicallyLeftCorner
  269. *
  270. * Draw the shadow effect of the bottom logically left (visually left for LTR, right for RTL window layout)
  271. * side of a rounded rectangular shadow.
  272. *
  273. * History:
  274. * 02/12/2001 Mohamed Sadek [msadek] created
  275. \***************************************************************************/
  276. _inline void DrawBottomLogicallyLeftCorner(VOID* pBits, LONG cx, BOOL fRTL)
  277. {
  278. LONG i, j;
  279. ULONG* ppixel;
  280. if (fRTL) {
  281. for (i = 0; i < CY_SHADOW; i++) {
  282. for (j = 0; j < CX_SHADOW; j++) {
  283. ppixel = (ULONG*)pBits + ((CY_SHADOW - i) * cx) - (2 * CX_SHADOW) + j;
  284. *ppixel = BottomLeftLTR[i][CX_SHADOW - 1 -j];
  285. }
  286. }
  287. } else {
  288. for (i = 0; i < CY_SHADOW; i++) {
  289. for (j = 0; j < CX_SHADOW; j++) {
  290. ppixel = (ULONG*)pBits + ((CY_SHADOW - i - 1) * cx) + CX_SHADOW + j;
  291. *ppixel = BottomLeftLTR[i][j];
  292. }
  293. }
  294. }
  295. }
  296. /***************************************************************************\
  297. * DrawRoundedRectangularShadow
  298. * Draw a rounded rectangular shadow effect.
  299. * Does not search for shadow pixel location in the bitmap but rather assumes
  300. * it to be the corners of the bitmap.
  301. *
  302. * History:
  303. * 02/12/2001 Mohamed Sadek [msadek] created
  304. \***************************************************************************/
  305. _inline void DrawRoundedRectangularShadow(VOID* pBits, LONG cx, LONG cy, BOOL fRTL)
  306. {
  307. DrawTopLogicallyRightCorner(pBits, cx, cy, fRTL);
  308. DrawLogicallyRightSide(pBits, cx, cy, fRTL);
  309. DrawBottomLogicallyRightCorner(pBits, cx, fRTL);
  310. DrawBottomSide(pBits, cx, fRTL);
  311. DrawBottomLogicallyLeftCorner(pBits, cx, fRTL);
  312. }
  313. /***************************************************************************\
  314. * DrawRegionalShadow
  315. * Search for shadow pixel location in the bitmap (those with gray scale in grgShadow
  316. * and adjust the alpha values.
  317. *
  318. *
  319. * History:
  320. * 05/08/2001 Mohamed Sadek [msadek] created
  321. \***************************************************************************/
  322. _inline void DrawRegionalShadow(VOID* pBits, LONG cx, LONG cy)
  323. {
  324. LONG i, j, k;
  325. ULONG* pixel;
  326. BYTE gs;
  327. for (i = 0; i < cy; i++) {
  328. for (j = 0; j < cx; j++) {
  329. pixel = (ULONG*)pBits + (cy - 1 - i) * cx + j;
  330. for (k = 0; k < C_SHADOW; k++) {
  331. gs = grgShadow[k];
  332. if (*pixel == ARGB(0, gs, gs, gs)) {
  333. *pixel = ALPHA(gs);
  334. }
  335. }
  336. }
  337. }
  338. }
  339. /***************************************************************************\
  340. * GenerateWindowShadow
  341. *
  342. \***************************************************************************/
  343. HBITMAP GenerateWindowShadow(PWND pwnd, HDC hdc)
  344. {
  345. BITMAPINFO bmi;
  346. HBITMAP hbm;
  347. VOID* pBits;
  348. LONG cx, cy;
  349. RECT rc;
  350. BOOL fRTL = TestWF(pwnd, WEFLAYOUTRTL);
  351. BOOL fSimpleRgn, fForceComplexRgn = FALSE;
  352. rc = pwnd->rcWindow;
  353. OffsetRect(&rc, -rc.left, -rc.top);
  354. /*
  355. * Doesn't make sense to have a shadow for a window with zero height or width
  356. */
  357. if (IsRectEmpty(&rc)) {
  358. return NULL;
  359. }
  360. rc.right += CX_SHADOW;
  361. rc.bottom += CY_SHADOW;
  362. cx = rc.right;
  363. cy = rc.bottom;
  364. /*
  365. * Create the DIB section.
  366. */
  367. RtlZeroMemory(&bmi, sizeof(bmi));
  368. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  369. bmi.bmiHeader.biWidth = cx;
  370. bmi.bmiHeader.biHeight = cy;
  371. bmi.bmiHeader.biPlanes = 1;
  372. bmi.bmiHeader.biBitCount = 32;
  373. bmi.bmiHeader.biCompression = BI_RGB;
  374. hbm = GreCreateDIBitmapReal(hdc, 0, NULL, &bmi, DIB_RGB_COLORS,
  375. sizeof(bmi), 0, NULL, 0, NULL, 0, 0, &pBits);
  376. if (hbm == NULL) {
  377. return NULL;
  378. }
  379. /*
  380. * Fill the dib section with the transparent color and then
  381. * draw the shadow on top of it.
  382. */
  383. GreSelectBitmap(hdc, hbm);
  384. FillRect(hdc, &rc, (HBRUSH)GreGetStockObject(BLACK_BRUSH));
  385. /*
  386. * Rectangular window shadow assumes the bitmap dimension to be greater than
  387. * or equal 2 * CX_SHADOW and 2 * CY_SHADOW else it will overrun bitmap buffer.
  388. * and in order to get a real rectangular shadow, the dimension should be 3 * CX_SHADOW
  389. * amd 3 * CY_SHADOW.
  390. */
  391. if ( (cx < 3 * CX_SHADOW) || (cy < 3 * CY_SHADOW)) {
  392. fForceComplexRgn = TRUE;
  393. }
  394. if (!DrawWindowShadow(pwnd, hdc, fRTL, fForceComplexRgn, &fSimpleRgn)) {
  395. return NULL;
  396. }
  397. if (fSimpleRgn && !fForceComplexRgn) {
  398. DrawRoundedRectangularShadow(pBits, cx, cy, fRTL);
  399. return hbm;
  400. }
  401. DrawRegionalShadow(pBits, cx, cy);
  402. return hbm;
  403. }
  404. /***************************************************************************\
  405. * FindShadow
  406. *
  407. \***************************************************************************/
  408. PSHADOW FindShadow(PWND pwnd)
  409. {
  410. PSHADOW pshadow;
  411. for (pshadow = gpshadowFirst; pshadow != NULL; pshadow = pshadow->pshadowNext) {
  412. if (pshadow->pwnd == pwnd) {
  413. return pshadow;
  414. }
  415. }
  416. return NULL;
  417. }
  418. /***************************************************************************\
  419. * WindowHasShadow
  420. *
  421. \***************************************************************************/
  422. BOOL WindowHasShadow(PWND pwnd)
  423. {
  424. BOOL fHasShadow = FALSE;
  425. if (TestWF(pwnd, WFVISIBLE)) {
  426. PSHADOW pshadow = FindShadow(pwnd);
  427. fHasShadow = (pshadow != NULL);
  428. } else {
  429. /*
  430. * The window isn't currently visible, so there is no shadow window.
  431. * We need to return if the window *would* have a shadow if it were
  432. * shown.
  433. */
  434. if (TestCF(pwnd, CFDROPSHADOW)) {
  435. fHasShadow = TRUE;
  436. if ((GETFNID(pwnd) == FNID_MENU) && (!TestALPHA(MENUFADE)) && TestEffectUP(MENUANIMATION)) {
  437. fHasShadow = FALSE;
  438. }
  439. }
  440. if (!TestALPHA(DROPSHADOW)) {
  441. fHasShadow = FALSE;
  442. }
  443. }
  444. return fHasShadow;
  445. }
  446. /***************************************************************************\
  447. * ApplyShadow
  448. *
  449. \***************************************************************************/
  450. BOOL ApplyShadow(PWND pwnd, PWND pwndShadow)
  451. {
  452. POINT pt, ptSrc = {0, 0};
  453. SIZE size;
  454. BLENDFUNCTION blend;
  455. HDC hdcShadow;
  456. HBITMAP hbmShadow;
  457. BOOL fRet;
  458. hdcShadow = GreCreateCompatibleDC(gpDispInfo->hdcScreen);
  459. if (hdcShadow == NULL) {
  460. return FALSE;
  461. }
  462. hbmShadow = GenerateWindowShadow(pwnd, hdcShadow);
  463. if (hbmShadow == NULL) {
  464. GreDeleteDC(hdcShadow);
  465. return FALSE;
  466. }
  467. pt.x = pwnd->rcWindow.left;
  468. pt.y = pwnd->rcWindow.top;
  469. size.cx = pwnd->rcWindow.right - pwnd->rcWindow.left + CX_SHADOW;
  470. size.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top + CY_SHADOW;
  471. if (TestWF(pwnd, WEFLAYOUTRTL)) {
  472. pt.x -= CX_SHADOW;
  473. }
  474. blend.BlendOp = AC_SRC_OVER;
  475. blend.BlendFlags = 0;
  476. blend.AlphaFormat = AC_SRC_ALPHA;
  477. blend.SourceConstantAlpha = 255;
  478. fRet = _UpdateLayeredWindow(pwndShadow, NULL, &pt, &size, hdcShadow, &ptSrc, 0,
  479. &blend, ULW_ALPHA);
  480. GreDeleteDC(hdcShadow);
  481. GreDeleteObject(hbmShadow);
  482. return fRet;
  483. }
  484. /***************************************************************************\
  485. * MoveShadow
  486. *
  487. \***************************************************************************/
  488. VOID MoveShadow(PWND pwnd)
  489. {
  490. PSHADOW pshadow = FindShadow(pwnd);
  491. POINT pt;
  492. if (pshadow == NULL) {
  493. return;
  494. }
  495. pt.x = pwnd->rcWindow.left;
  496. pt.y = pwnd->rcWindow.top;
  497. _UpdateLayeredWindow(pshadow->pwndShadow, NULL, &pt, NULL, NULL, NULL, 0, NULL, 0);
  498. }
  499. /***************************************************************************\
  500. * UpdateShadowShape
  501. *
  502. \***************************************************************************/
  503. VOID UpdateShadowShape(PWND pwnd)
  504. {
  505. PSHADOW pshadow = FindShadow(pwnd);
  506. if (pshadow == NULL) {
  507. return;
  508. }
  509. ApplyShadow(pshadow->pwnd, pshadow->pwndShadow);
  510. }
  511. /***************************************************************************\
  512. * xxxUpdateShadowZorder
  513. *
  514. \***************************************************************************/
  515. VOID xxxUpdateShadowZorder(PWND pwnd)
  516. {
  517. TL tlpwnd;
  518. PWND pwndShadow;
  519. PSHADOW pshadow = FindShadow(pwnd);
  520. if (pshadow == NULL) {
  521. return;
  522. }
  523. pwndShadow = pshadow->pwndShadow;
  524. if (TestWF(pwnd, WEFTOPMOST) && !TestWF(pwndShadow, WEFTOPMOST)) {
  525. SetWF(pwndShadow, WEFTOPMOST);
  526. } else if (!TestWF(pwnd, WEFTOPMOST) && TestWF(pwndShadow, WEFTOPMOST)) {
  527. ClrWF(pwndShadow, WEFTOPMOST);
  528. }
  529. ThreadLock(pwndShadow, &tlpwnd);
  530. xxxSetWindowPos(pwndShadow, pwnd, 0, 0, 0, 0, SWP_NOACTIVATE |
  531. SWP_NOSIZE | SWP_NOMOVE);
  532. ThreadUnlock(&tlpwnd);
  533. }
  534. /***************************************************************************\
  535. * xxxRemoveShadow
  536. *
  537. * Given the shadowed window, destroy the shadow window, cleanup the
  538. * memory used by the shadow structure and remove it from the list.
  539. \***************************************************************************/
  540. VOID xxxRemoveShadow(PWND pwnd)
  541. {
  542. PSHADOW* ppshadow;
  543. PSHADOW pshadow;
  544. PWND pwndT;
  545. CheckLock(pwnd);
  546. ppshadow = &gpshadowFirst;
  547. while (*ppshadow != NULL) {
  548. pshadow = *ppshadow;
  549. if (pshadow->pwnd == pwnd) {
  550. pwndT = pshadow->pwndShadow;
  551. *ppshadow = pshadow->pshadowNext;
  552. UserFreePool(pshadow);
  553. xxxDestroyWindow(pwndT);
  554. break;
  555. }
  556. ppshadow = &pshadow->pshadowNext;
  557. }
  558. }
  559. /***************************************************************************\
  560. * RemoveShadow
  561. *
  562. * Given a shadow structure pointer, search for it in the list and remove it
  563. \***************************************************************************/
  564. VOID RemoveShadow(PSHADOW pshadow)
  565. {
  566. PSHADOW* ppshadow;
  567. PSHADOW pshadowT;
  568. ppshadow = &gpshadowFirst;
  569. while (*ppshadow != NULL) {
  570. pshadowT = *ppshadow;
  571. if (pshadowT == pshadow) {
  572. *ppshadow = pshadowT->pshadowNext;
  573. UserFreePool(pshadowT);
  574. break;
  575. }
  576. ppshadow = &pshadowT->pshadowNext;
  577. }
  578. }
  579. /***************************************************************************\
  580. * CleanupShadow
  581. *
  582. * Given the shadow window, remove the shadow structure from the list and
  583. * cleanup the memory used by the shadow structure.
  584. \***************************************************************************/
  585. VOID CleanupShadow(PWND pwndShadow)
  586. {
  587. PSHADOW* ppshadow;
  588. PSHADOW pshadow;
  589. CheckLock(pwndShadow);
  590. ppshadow = &gpshadowFirst;
  591. while (*ppshadow != NULL) {
  592. pshadow = *ppshadow;
  593. if (pshadow->pwndShadow == pwndShadow) {
  594. *ppshadow = pshadow->pshadowNext;
  595. UserFreePool(pshadow);
  596. break;
  597. }
  598. ppshadow = &pshadow->pshadowNext;
  599. }
  600. }
  601. /***************************************************************************\
  602. * xxxAddShadow
  603. *
  604. \***************************************************************************/
  605. BOOL xxxAddShadow(PWND pwnd)
  606. {
  607. PWND pwndShadow;
  608. DWORD ExStyle;
  609. TL tlpwnd;
  610. TL tlpool;
  611. PSHADOW pshadow;
  612. CheckLock(pwnd);
  613. if (!TestALPHA(DROPSHADOW)) {
  614. return FALSE;
  615. }
  616. if (FindShadow(pwnd)) {
  617. return TRUE;
  618. }
  619. if ((pshadow = (PSHADOW)UserAllocPool(sizeof(SHADOW), TAG_SHADOW)) == NULL) {
  620. return FALSE;
  621. }
  622. ThreadLockPool(PtiCurrent(), pshadow, &tlpool);
  623. ExStyle = WS_EX_TOOLWINDOW | WS_EX_LAYERED | WS_EX_TRANSPARENT;
  624. if (TestWF(pwnd, WEFTOPMOST)) {
  625. ExStyle |= WS_EX_TOPMOST;
  626. }
  627. pwndShadow = xxxNVCreateWindowEx(ExStyle, (PLARGE_STRING)gatomShadow,
  628. NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, hModuleWin, NULL, WINVER);
  629. if (pwndShadow == NULL || !ApplyShadow(pwnd, pwndShadow)) {
  630. UserFreePool(pshadow);
  631. ThreadUnlockPool(PtiCurrent(), &tlpool);
  632. if (pwndShadow != NULL) {
  633. ThreadLock(pwndShadow, &tlpwnd);
  634. xxxDestroyWindow(pwndShadow);
  635. ThreadUnlock(&tlpwnd);
  636. }
  637. return FALSE;
  638. }
  639. pshadow->pshadowNext = gpshadowFirst;
  640. gpshadowFirst = pshadow;
  641. pshadow->pwnd = pwnd;
  642. pshadow->pwndShadow = pwndShadow;
  643. /*
  644. * Since we added it the global list, we need to change the way
  645. * we lock its pool.
  646. */
  647. ThreadUnlockPool(PtiCurrent(), &tlpool);
  648. ThreadLockPoolCleanup(PtiCurrent(), pshadow, &tlpool, RemoveShadow);
  649. ThreadLock(pwndShadow, &tlpwnd);
  650. xxxSetWindowPos(pwndShadow, pwnd, 0, 0, 0, 0, SWP_SHOWWINDOW |
  651. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
  652. ThreadUnlock(&tlpwnd);
  653. ThreadUnlockPool(PtiCurrent(), &tlpool);
  654. return TRUE;
  655. }
  656. /***************************************************************************\
  657. * FAnyShadows
  658. *
  659. \***************************************************************************/
  660. BOOL FAnyShadows(VOID)
  661. {
  662. return (gpshadowFirst != NULL);
  663. }