00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
#include "precomp.h"
00014
#pragma hdrstop
00015
00016
00017
00018
00019
00020 #define CEXCLUDERECTSMAX 30
00021 #define CEXCLUDEPWNDSMAX 30
00022
00023
00024 BOOL gfVisAlloc;
00025 int gcrcVisExclude;
00026 int gcrcVisExcludeMax;
00027 PWND *
gapwndVisExclude;
00028 PWND *
gapwndVisDefault;
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
BOOL
00040 SetRectRgnIndirect(HRGN hrgn, LPCRECT lprc)
00041 {
00042
return GreSetRectRgn(hrgn, lprc->left, lprc->top, lprc->right, lprc->bottom);
00043 }
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 HRGN
00057 CreateEmptyRgn(
void)
00058 {
00059
return GreCreateRectRgnIndirect(
PZERO(RECT));
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 HRGN
00074 CreateEmptyRgnPublic(
void)
00075 {
00076 HRGN hrgn;
00077
00078
if (hrgn =
CreateEmptyRgn()) {
00079 UserVerify(GreSetRegionOwner(hrgn, OBJECT_OWNER_PUBLIC));
00080 }
00081
00082
return hrgn;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
BOOL
00097 SetEmptyRgn(HRGN hrgn)
00098 {
00099
return SetRectRgnIndirect(hrgn,
PZERO(RECT));
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 HRGN
00115 SetOrCreateRectRgnIndirectPublic(HRGN * phrgn, LPCRECT lprc)
00116 {
00117
if (*phrgn) {
00118 UserVerify(
SetRectRgnIndirect(*phrgn, lprc));
00119 }
else if (*phrgn = GreCreateRectRgnIndirect((LPRECT) lprc)) {
00120 UserVerify(GreSetRegionOwner(*phrgn, OBJECT_OWNER_PUBLIC));
00121 }
00122
00123
return *phrgn;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 BOOL ResizeVisExcludeMemory(VOID)
00141 {
00142
int crcNew;
00143
PWND apwndNew;
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 crcNew =
gcrcVisExcludeMax +
CEXCLUDEPWNDSMAX;
00154 apwndNew = (
PWND)UserAllocPool(
00155 crcNew *
sizeof(
PWND), TAG_VISRGN);
00156
00157
if (!apwndNew)
00158
return FALSE;
00159
00160 UserAssert(
gcrcVisExcludeMax ==
gcrcVisExclude);
00161 RtlCopyMemory(apwndNew,
gapwndVisExclude,
gcrcVisExcludeMax *
sizeof(
PWND));
00162
if (
gfVisAlloc) {
00163 UserFreePool(
gapwndVisExclude);
00164 }
else {
00165
gfVisAlloc =
TRUE;
00166 }
00167
00168
gcrcVisExcludeMax = crcNew;
00169
gapwndVisExclude = (
PWND *)apwndNew;
00170
return TRUE;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 #define CheckIntersectRect(prc1, prc2) \
00189
( prc1->left < prc2->right \
00190
&& prc2->left < prc1->right \
00191
&& prc1->top < prc2->bottom \
00192
&& prc2->top < prc1->bottom)
00193
00194 #define EmptyRect(prc) \
00195
( prc->left >= prc->right \
00196
|| prc->top >= prc->bottom)
00197
00198 BOOL ExcludeWindowRects(
00199
PWND pwnd ,
00200
PWND pwndStop,
00201 LPRECT lprcIntersect)
00202 {
00203 PRECT prc;
00204
00205
#if DBG
00206
if (pwnd !=
NULL && pwndStop !=
NULL &&
00207 pwnd->
spwndParent != pwndStop->
spwndParent) {
00208 RIPMSG0(RIP_ERROR,
"ExcludeWindowRects: bad windows passed in");
00209 }
00210
#endif
00211
00212
while ((pwnd !=
NULL) && (pwnd != pwndStop)) {
00213 UserAssert(pwnd);
00214 prc = &pwnd->
rcWindow;
00215
if (
TestWF(pwnd,
WFVISIBLE)
00216 && !
FLayeredOrRedirected(pwnd)
00217 && (
TestWF(pwnd,
WEFTRANSPARENT) == 0)
00218 &&
CheckIntersectRect(lprcIntersect, prc)
00219 && !
EmptyRect(prc)) {
00220
00221 UserAssert(
gcrcVisExclude <=
gcrcVisExcludeMax);
00222
if (
gcrcVisExclude ==
gcrcVisExcludeMax) {
00223
if (!
ResizeVisExcludeMemory()) {
00224
return FALSE;
00225 }
00226 }
00227
00228
gapwndVisExclude[
gcrcVisExclude++] = pwnd;
00229 }
00230
00231 pwnd = pwnd->
spwndNext;
00232 }
00233
00234
return TRUE;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 BOOL CalcWindowVisRgn(
00251
PWND pwnd,
00252 HRGN *phrgn,
00253 DWORD flags)
00254 {
00255 RECT rcWindow;
00256
PWND pwndParent;
00257
PWND pwndRoot;
00258
PWND pwndLoop;
00259
BOOL fClipSiblings;
00260
BOOL fRgnParent =
FALSE;
00261
BOOL fResult;
00262
PWND apwndVisDefault[
CEXCLUDEPWNDSMAX];
00263
00264
00265
00266
00267
00268
00269 rcWindow = (flags & DCX_WINDOW ? pwnd->
rcWindow : pwnd->
rcClient);
00270
00271
00272
00273
00274
00275
00276
00277 pwndRoot = pwnd->
head.rpdesk->pDeskInfo->spwnd->spwndParent;
00278 pwndParent = pwnd->
spwndParent;
00279
00280
00281
00282
00283
00284
if (pwndParent ==
NULL) {
00285
#if DBG
00286
if (pwnd != pwndRoot) {
00287 RIPMSG0(RIP_ERROR,
"CalcWindowVisRgn: pwndParent is NULL");
00288 }
00289
#endif
00290
goto NullRegion;
00291 }
00292
00293
while (pwndParent != pwndRoot) {
00294
00295
00296
00297
00298
00299
00300
if ((flags & DCX_LAYERED) && (
GETFNID(pwndParent) ==
FNID_DESKTOP))
00301
break;
00302
00303
00304
00305
00306
if (pwndParent->
hrgnClip !=
NULL)
00307 fRgnParent =
TRUE;
00308
00309
00310
00311
00312
if (!
IntersectRect(&rcWindow, &rcWindow, &pwndParent->
rcClient))
00313
goto NullRegion;
00314
00315 pwndParent = pwndParent->
spwndParent;
00316 }
00317
00318
00319
00320
00321
00322
gapwndVisDefault = apwndVisDefault;
00323
gapwndVisExclude =
gapwndVisDefault;
00324
gcrcVisExcludeMax =
ARRAY_SIZE(apwndVisDefault);
00325
gcrcVisExclude = 0;
00326
00327
00328
00329
00330 fClipSiblings = (
BOOL)(flags & DCX_CLIPSIBLINGS);
00331 pwndParent = pwnd->
spwndParent;
00332 pwndLoop = pwnd;
00333
00334
while (pwndParent != pwndRoot) {
00335
00336
00337
00338
00339
00340
00341
if ((flags & DCX_LAYERED) &&
FLayeredOrRedirected(pwndLoop)) {
00342 fClipSiblings =
FALSE;
00343 }
00344
00345
00346
00347
00348
if (fClipSiblings && (pwndParent->
spwndChild != pwndLoop)) {
00349
00350
if (!
ExcludeWindowRects(pwndParent->
spwndChild,
00351 pwndLoop,
00352 &rcWindow)) {
00353
00354
goto NullRegion;
00355 }
00356 }
00357
00358
00359
00360
00361
00362 fClipSiblings =
TestWF(pwndParent,
WFCLIPSIBLINGS);
00363
00364 pwndLoop = pwndParent;
00365 pwndParent = pwndLoop->
spwndParent;
00366 }
00367
00368
if ((flags & DCX_CLIPCHILDREN) && (pwnd->spwndChild !=
NULL)) {
00369
00370
if (!
ExcludeWindowRects(pwnd->spwndChild,
NULL, &rcWindow)) {
00371
goto NullRegion;
00372 }
00373 }
00374
00375
00376
00377
00378
00379
00380
if (
gcrcVisExclude > 0) {
00381
00382 RECT arcVisRects[
CEXCLUDERECTSMAX];
00383 PRECT arcExclude;
00384
int i;
00385
int ircVisExclude = 0;
00386
int irgnVisExclude = 0;
00387
00388
00389
00390
00391
00392
00393
00394
if (
gcrcVisExclude <=
CEXCLUDERECTSMAX) {
00395 arcExclude = arcVisRects;
00396 }
else {
00397 arcExclude = (PRECT)UserAllocPoolWithQuota(
00398
sizeof(RECT) *
gcrcVisExclude, TAG_VISRGN);
00399
00400
if (!arcExclude)
00401
goto NullRegion;
00402 }
00403
00404
00405
00406
00407
00408
00409
for (i = 0; i <
gcrcVisExclude; i++) {
00410
00411
00412
00413
00414
00415
00416
if (
gapwndVisExclude[i]->
hrgnClip !=
NULL) {
00417
00418
gapwndVisExclude[irgnVisExclude++] =
gapwndVisExclude[i];
00419
continue;
00420 }
00421
00422
00423
00424
00425
00426 arcExclude[ircVisExclude++] =
gapwndVisExclude[i]->
rcWindow;
00427 }
00428
00429
if (*phrgn ==
NULL)
00430 *phrgn =
CreateEmptyRgn();
00431
00432
if (ircVisExclude != 0) {
00433 GreSubtractRgnRectList(*phrgn,
00434 &rcWindow,
00435 arcExclude,
00436 ircVisExclude);
00437 }
else {
00438
SetRectRgnIndirect(*phrgn, &rcWindow);
00439 }
00440
00441
for (i = 0; i < irgnVisExclude; i++) {
00442
00443
SetRectRgnIndirect(
ghrgnInv2, &
gapwndVisExclude[i]->rcWindow);
00444
IntersectRgn(
ghrgnInv2,
ghrgnInv2,
gapwndVisExclude[i]->hrgnClip);
00445
00446
if (
SubtractRgn(*phrgn, *phrgn,
ghrgnInv2) == NULLREGION)
00447
break;
00448 }
00449
00450
if (arcExclude != arcVisRects) {
00451 UserFreePool((HLOCAL)arcExclude);
00452 }
00453
00454 }
else {
00455
00456
00457
00458
00459
00460
if (
TestWF(pwnd,
WFDESTROYED)) {
00461
SetRectEmpty(&rcWindow);
00462 }
00463
00464
00465
00466
00467
00468
SetOrCreateRectRgnIndirectPublic(phrgn, &rcWindow);
00469 }
00470
00471
00472
00473
00474
if (pwnd->hrgnClip !=
NULL) {
00475
IntersectRgn(*phrgn, *phrgn, pwnd->hrgnClip);
00476 }
00477
00478
00479
00480
00481
if (fRgnParent) {
00482
00483
PWND pwndT;
00484
00485
for (pwndT = pwnd->
spwndParent;
00486 pwndT != pwndRoot;
00487 pwndT = pwndT->
spwndParent) {
00488
00489
if (pwndT->
hrgnClip !=
NULL) {
00490
00491
if (
IntersectRgn(*phrgn, *phrgn, pwndT->
hrgnClip) == NULLREGION)
00492
break;
00493 }
00494 }
00495 }
00496
00497 fResult =
TRUE;
00498
00499
00500 Cleanup:
00501
if (
gfVisAlloc) {
00502 UserFreePool((HLOCAL)
gapwndVisExclude);
00503
gfVisAlloc =
FALSE;
00504 }
00505
00506
return fResult;
00507
00508 NullRegion:
00509
SetOrCreateRectRgnIndirectPublic(phrgn,
PZERO(RECT));
00510 fResult =
FALSE;
00511
goto Cleanup;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 BOOL CalcVisRgn(
00524 HRGN *phrgn,
00525
PWND pwndOrg,
00526
PWND pwndClip,
00527 DWORD flags)
00528 {
00529
PDESKTOP pdesk;
00530
00531 UserAssert(pwndOrg !=
NULL);
00532
00533
00534
00535
00536
00537
00538 pdesk = pwndOrg->
head.rpdesk;
00539
00540 UserAssert(pdesk);
00541
00542
00543
00544
00545
#if DBG
00546
if (
grpdeskRitInput !=
NULL) {
00547 UserAssert(pdesk->
rpwinstaParent ==
grpdeskRitInput->
rpwinstaParent ||
00548 !
IsVisible(pwndOrg));
00549 }
00550
#endif // DBG
00551
00552
if (!
IsVisible(pwndOrg) || pdesk !=
grpdeskRitInput) {
00553
goto EmptyRgn;
00554 }
00555
00556
00557
00558
00559
00560
if ((
gspwndLockUpdate !=
NULL) &&
00561 !(flags & DCX_LOCKWINDOWUPDATE) &&
00562
_IsDescendant(
gspwndLockUpdate, pwndOrg)) {
00563
00564
goto EmptyRgn;
00565 }
00566
00567
00568
00569
00570
return CalcWindowVisRgn(pwndClip, phrgn, flags);
00571
00572 EmptyRgn:
00573
SetOrCreateRectRgnIndirectPublic(phrgn,
PZERO(RECT));
00574
return FALSE;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 int CalcWindowRgn(
00586
PWND pwnd,
00587 HRGN hrgn,
00588 BOOL fClient)
00589 {
00590
SetRectRgnIndirect(hrgn, (fClient) ? &pwnd->
rcClient : &pwnd->
rcWindow);
00591
00592
00593
00594
00595
00596
if (pwnd->
hrgnClip !=
NULL) {
00597
return IntersectRgn(hrgn, hrgn, pwnd->
hrgnClip);
00598 }
00599
00600
return SIMPLEREGION;
00601 }