Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

spb.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

BOOL FBitsTouch (PWND pwndDirty, LPRECT lprcDirty, PSPB pspb, DWORD flags)
BOOL SpbCheckRect2 (PSPB pspb, PWND pwnd, LPRECT lprc, DWORD flags)
BOOL SpbTransfer (PSPB pspb, PWND pwnd, BOOL fChildren)
VOID CreateSpb (PWND pwnd, UINT flags, HDC hdcScreen)
UINT RestoreSpb (PWND pwnd, HRGN hrgnUncovered, HDC *phdcScreen)
BOOL LockWindowUpdate2 (PWND pwndLock, BOOL fThreadOverride)
PSPB FindSpb (PWND pwnd)
VOID SpbCheck (VOID)
VOID SpbCheckDce (PDCE pdce)
VOID SpbCheckRect (PWND pwnd, LPRECT lprc, DWORD flags)
VOID SpbCheckPwnd (PWND pwnd)
VOID FreeSpb (PSPB pspb)
VOID FreeAllSpbs (void)


Function Documentation

VOID CreateSpb PWND  pwnd,
UINT  flags,
HDC  hdcScreen
 

Definition at line 341 of file spb.c.

References _MonitorFromRect(), AnySpbs, BOOL, cy, tagDCE::DCX_flags, FALSE, tagSPB::flags, ghdcMem, ghrgnSPB2, gpDispInfo, tagSPB::hbm, tagDCE::hdc, tagDISPLAYINFO::hDev, tagSPB::hrgn, tagWND::hrgnClip, tagDISPLAYINFO::hrgnScreen, IntersectRect(), IntersectRgn, Lock, NULL, tagDISPLAYINFO::pdceFirst, tagDCE::pdceNext, tagDISPLAYINFO::pMonitorPrimary, tagDISPLAYINFO::pspbFirst, tagSPB::pspbNext, PWNDDESKTOP, tagSPB::rc, tagMONITOR::rcMonitor, tagDISPLAYINFO::rcScreen, tagWND::rcWindow, SetRectRgnIndirect(), SetWF, SPB, SPB_LOCKUPDATE, SPB_SAVESCREENBITS, SpbCheck(), SpbTransfer(), tagSPB::spwnd, tagWND::spwndNext, tagWND::spwndParent, SubtractRect(), SYSMET, TRUE, tagSPB::ulSaveId, Unlock, VOID(), and WFHASSPB.

Referenced by LockWindowUpdate2(), and zzzChangeStates().

00345 { 00346 PSPB pspb; 00347 int fSpbLockUpdate; 00348 00349 /* 00350 * Non-LOCKWINDOWUPDATE SPBs can only be created for top-level windows. 00351 * 00352 * This is because of the way that the display driver RestoreBits function 00353 * works. It can put bits down in places that aren't even part of the 00354 * window's visrgn, and these bits need to be invalidated. The 00355 * SetWindowPos() code to handle this case only knows how to invalidate 00356 * one of windows (i.e., the window's immediate parent), but all levels 00357 * need to get invalidated. See also the comments in wmswp.c, near the 00358 * call to RestoreSpb(). 00359 * 00360 * For example: the Q&E app brings up a copyright dialog that is a child 00361 * of its main window. While this is up, the user alt-f alt-l to execute 00362 * the file login command, which brings up another dialog that is a child 00363 * of the desktop. When the copyright dialog goes away, the display driver 00364 * restores bits on top of the second dialog. The SWP code knows to 00365 * invalidate the bogus stuff in the main window, but not in the desktop. 00366 * 00367 * LOCKUPDATE SPBs are fine, because they don't call RestoreBits. 00368 */ 00369 fSpbLockUpdate = flags & SPB_LOCKUPDATE; 00370 if ( !fSpbLockUpdate && 00371 pwnd->spwndParent != NULL && 00372 pwnd->spwndParent != PWNDDESKTOP(pwnd)) { 00373 00374 return; 00375 } 00376 00377 /* 00378 * We go and check all the existing DCs at this point, to handle the 00379 * case where we're saving an image of a window that has a "dirty" 00380 * DC, which would eventually invalidate our saved image (but which 00381 * is really okay). 00382 */ 00383 if (AnySpbs()) { 00384 00385 SpbCheck(); 00386 00387 } else { 00388 00389 PDCE pdce; 00390 00391 /* 00392 * Reset the dirty areas of all of the DC's and enable 00393 * bounds accumulation. We're creating a SPB now. This 00394 * is only done if there are no other SPB's in the list. 00395 */ 00396 GreLockDisplay(gpDispInfo->hDev); 00397 00398 for (pdce = gpDispInfo->pdceFirst; pdce != NULL; pdce = pdce->pdceNext) { 00399 00400 if (pdce->DCX_flags & DCX_LAYERED) 00401 continue; 00402 00403 GreGetBounds(pdce->hdc, NULL, GGB_ENABLE_WINMGR); 00404 } 00405 00406 GreUnlockDisplay(gpDispInfo->hDev); 00407 } 00408 00409 /* 00410 * Create the save popup bits structure 00411 */ 00412 pspb = (PSPB)UserAllocPoolWithQuota(sizeof(SPB), TAG_SPB); 00413 if (!pspb) 00414 return; 00415 00416 pspb->spwnd = NULL; 00417 pspb->rc = pwnd->rcWindow; 00418 00419 /* 00420 * Clip to the screen 00421 */ 00422 if (!IntersectRect(&pspb->rc, &pspb->rc, &gpDispInfo->rcScreen)) 00423 goto BMError; 00424 00425 pspb->hrgn = NULL; 00426 pspb->hbm = NULL; 00427 pspb->flags = flags; 00428 Lock(&(pspb->spwnd), pwnd); 00429 00430 if (!fSpbLockUpdate) { 00431 00432 RECT rc = pspb->rc; 00433 00434 if (!SYSMET(SAMEDISPLAYFORMAT)) { 00435 PMONITOR pMonitor = _MonitorFromRect(&pspb->rc, MONITOR_DEFAULTTOPRIMARY); 00436 RECT rcT; 00437 00438 /* 00439 * If the intersection with the monitor isn't the entire visible 00440 * window rectangle, then bail! We don't save SPBs for windows 00441 * that span multiple monitors. Since we do a lot of work to 00442 * pin dialogs and menus, there won't be too many of these 00443 * babies. 00444 */ 00445 if (SubtractRect(&rcT, &pspb->rc, &pMonitor->rcMonitor) && 00446 GreRectInRegion(gpDispInfo->hrgnScreen, &rcT)) 00447 goto BMError2; 00448 00449 /* 00450 * Clip to the window's monitor 00451 */ 00452 if (!IntersectRect(&pspb->rc, &pspb->rc, &pMonitor->rcMonitor)) 00453 goto BMError2; 00454 00455 /* 00456 * dont save bits in a mixed bitdepth situtation 00457 * we cant create the exactly correct format bitmap 00458 * in all cases (555/565, and Paletized) so as 00459 * a cop-out dont save bitmaps at all (on secondaries) 00460 * in mixed bit-depth. 00461 * 00462 * the correct fix is to create a compatible 00463 * bitmap for the monitor device and directly 00464 * BitBlt() from/to the device (pMonitor->hdcMonitor) 00465 * but this involves too much code at this time. 00466 */ 00467 if (pMonitor != gpDispInfo->pMonitorPrimary) 00468 goto BMError2; 00469 } 00470 00471 /* 00472 * If this window is a regional window, don't use driver save 00473 * bits. Because it can only restore an entire rectangle, 00474 * invalid region is calculated assuming the old vis rgn was 00475 * rectangular. For regional windows, this would end up always 00476 * invalidating the area of (rcWindow - hrgnWindow) every 00477 * time an spb would be used. On the other hand, the invalid 00478 * area calculated when not using driver save bits is perfect, 00479 * because the restore blt can be correctly clipped to begin with. 00480 */ 00481 if ((pwnd->hrgnClip == NULL) && 00482 (pspb->ulSaveId = GreSaveScreenBits(gpDispInfo->hDev, 00483 SS_SAVE, 00484 0, 00485 (RECTL *)&rc))) { 00486 00487 /* 00488 * Remember that we copied this bitmap into on board memory. 00489 */ 00490 pspb->flags |= SPB_SAVESCREENBITS; 00491 00492 } else { 00493 HBITMAP hbmSave; 00494 BOOL bRet; 00495 00496 /* 00497 * The following delta byte-aligns the screen bitmap 00498 */ 00499 int dx = pspb->rc.left & 0x0007; 00500 int cx = pspb->rc.right - pspb->rc.left; 00501 int cy = pspb->rc.bottom - pspb->rc.top; 00502 00503 /* 00504 * NOTE: we don't care about setting up a visrgn in 00505 * hdcScreen, because BitBlt ignores it on reads. 00506 */ 00507 pspb->hbm = GreCreateCompatibleBitmap(hdcScreen, cx + dx, cy); 00508 if (!pspb->hbm) 00509 goto BMError2; 00510 00511 hbmSave = (HBITMAP)GreSelectBitmap(ghdcMem, pspb->hbm); 00512 if (!hbmSave) 00513 goto BMError2; 00514 00515 /* 00516 * Copy the contents of the screen to the bitmap in the 00517 * save popup bits structure. If we ever find we run 00518 * into problems with the screen access check we can 00519 * do a bLockDisplay, give this process permission, do 00520 * the BitBlt and then take away permission. GDI 00521 * accesses the screen and that bit only under the 00522 * display semaphore so it is safe. Alternatively 00523 * if it is too hard to change this processes permission 00524 * here we could do it in GDI by marking the psoSrc 00525 * readable temporarily while completing the operation 00526 * and then setting it back to unreadable when done. 00527 * Or we could just fail it like the CreateCompatibleDC 00528 * failed and force a redraw. Basically we can't add 00529 * 3K of code in GDI to do a BitBlt that just does 1 00530 * test differently for this 1 place in User. 00531 * 00532 */ 00533 bRet = GreBitBlt(ghdcMem, 00534 dx, 00535 0, 00536 cx, 00537 cy, 00538 hdcScreen, 00539 pspb->rc.left, 00540 pspb->rc.top, 00541 0x00CC0000, 00542 0); 00543 00544 GreSelectBitmap(ghdcMem, hbmSave); 00545 00546 if (!bRet) 00547 goto BMError2; 00548 00549 GreSetBitmapOwner(pspb->hbm, OBJECT_OWNER_PUBLIC); 00550 } 00551 00552 /* 00553 * Mark that the window has an SPB. 00554 */ 00555 SetWF(pwnd, WFHASSPB); 00556 00557 /* 00558 * non-LOCKUPDATE SPBs are not invalidated by 00559 * drawing in pspb->spwnd, so start the SPB validation 00560 * loop below at the sibling immediately below us. 00561 */ 00562 pwnd = pwnd->spwndNext; 00563 } 00564 00565 /* 00566 * Link the new save popup bits structure into the list. 00567 */ 00568 pspb->pspbNext = gpDispInfo->pspbFirst; 00569 gpDispInfo->pspbFirst = pspb; 00570 00571 /* 00572 * Here we deal with any update regions that may be 00573 * pending in windows underneath the SPB. 00574 * 00575 * For all windows that might affect this SPB: 00576 * - Subtract the SPB rect from the update region 00577 * - Subtract the window from the SPB 00578 * 00579 * Note that we use pspb->spwnd here, in case it has 00580 * no siblings. 00581 * 00582 * ghrgnSPB2 is the region that is used inside of SpbTransfer to 00583 * validate window update regions. Intersect with the window clipping 00584 * region, if it exists. Don't want to intersect with the spb rect if 00585 * a clipping region exists because we'll end up validating more than 00586 * we want to validate. 00587 */ 00588 SetRectRgnIndirect(ghrgnSPB2, &pspb->rc); 00589 if (pspb->spwnd->hrgnClip != NULL) { 00590 00591 /* 00592 * If we get an error bail since an error might result in more 00593 * being validated than we want. Since the below code is only an 00594 * optimizer, this is ok: the window will remain invalid and will 00595 * draw, thereby invalidating the SPB like usual. 00596 */ 00597 if (IntersectRgn(ghrgnSPB2, 00598 ghrgnSPB2, 00599 pspb->spwnd->hrgnClip) == ERROR) { 00600 return; 00601 } 00602 } 00603 00604 if (pspb->spwnd->spwndParent == NULL || 00605 SpbTransfer(pspb, pspb->spwnd->spwndParent, FALSE)) { 00606 00607 /* 00608 * Do the same for the siblings underneath us... 00609 */ 00610 for ( ; pwnd != NULL; pwnd = pwnd->spwndNext) { 00611 if (!SpbTransfer(pspb, pwnd, TRUE)) 00612 break; 00613 } 00614 } 00615 00616 return; 00617 00618 BMError2: 00619 /* 00620 * Error creating the bitmap: clean up and return. 00621 */ 00622 if (pspb->hbm) 00623 GreDeleteObject(pspb->hbm); 00624 00625 Unlock(&pspb->spwnd); 00626 // fall-through 00627 00628 BMError: 00629 UserFreePool(pspb); 00630 }

BOOL FBitsTouch PWND  pwndDirty,
LPRECT  lprcDirty,
PSPB  pspb,
DWORD  flags
 

Definition at line 34 of file spb.c.

References BOOL, FALSE, tagSPB::flags, tagWND::hrgnClip, IntersectRect(), IsVisible(), NULL, tagSPB::rc, tagWND::rcWindow, SPB_LOCKUPDATE, tagSPB::spwnd, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, SubtractRect(), TestWF, and WFVISIBLE.

Referenced by SpbCheckRect2().

00039 { 00040 PWND pwndSpb, 00041 pwndDirtySave; 00042 int fSpbLockUpdate; 00043 00044 /* 00045 * When no window is passed in, skip all the window-related stuff and 00046 * go directly to check the rectangle. 00047 */ 00048 if (pwndDirty == NULL) 00049 goto ProbablyTouch; 00050 00051 /* 00052 * If pwndDirty or its parents are invisible, 00053 * then it can't invalidate any SPBs 00054 */ 00055 if (!IsVisible(pwndDirty)) 00056 return FALSE; 00057 00058 pwndSpb = pspb->spwnd; 00059 fSpbLockUpdate = pspb->flags & SPB_LOCKUPDATE; 00060 if (fSpbLockUpdate) { 00061 00062 /* 00063 * If the guy is drawing through a locked window via 00064 * DCX_LOCKWINDOWUPDATE and the spb is a LOCKUPDATE SPB, then 00065 * don't do any invalidation of the SPB. Basically we're trying 00066 * to avoid having the tracking rectangle invalidate the SPB 00067 * since it's drawn via a WinGetClipPS() ps. 00068 */ 00069 if (flags & DCX_LOCKWINDOWUPDATE) 00070 return FALSE; 00071 } 00072 00073 /* 00074 * If pwndDirty is pwndSpb's immediate parent (e.g., drawing in the 00075 * desktop window behind a dialog box), then we may touch: do the 00076 * intersection. 00077 */ 00078 if (pwndDirty == pwndSpb->spwndParent) 00079 goto ProbablyTouch; 00080 00081 /* 00082 * We know that pwndDirty != pwndSpb->spwndParent. 00083 * Now find the parent of pwndDirty that is a sibling of pwndSpb. 00084 */ 00085 pwndDirtySave = pwndDirty; 00086 00087 while (pwndSpb->spwndParent != pwndDirty->spwndParent) { 00088 pwndDirty = pwndDirty->spwndParent; 00089 00090 /* 00091 * If we get to the top of the tree, it's because: 00092 * 1. pwndSpb == pwndDesktop 00093 * 2. pwndDirty is a parent of pwndSpb 00094 * 3. pwndDirty == pwndDesktop 00095 * 4. pwndDirty is a child of some other desktop 00096 * 5. pwndSpb and pwndDirty aren't siblings 00097 * 00098 * In all these cases, pwndDirty can't touch pwndSpb. 00099 */ 00100 if (pwndDirty == NULL) 00101 return FALSE; 00102 } 00103 00104 /* 00105 * If pwndSpb is the same as pwndDirty, then it will invalidate 00106 * only if the SPB is LOCKUPDATE. 00107 * 00108 * Non-LOCKUPDATE SPB's can't be invalidated by their 00109 * own windows, but LOCKUPDATE SPB's can. 00110 */ 00111 if (pwndDirty == pwndSpb) { 00112 if (!fSpbLockUpdate) 00113 return FALSE; 00114 00115 /* 00116 * If pwndSpb itself was drawn in, then we can't 00117 * try subtracting children. 00118 */ 00119 if (pwndDirtySave == pwndSpb) 00120 goto ProbablyTouch; 00121 00122 /* 00123 * We want to calculate the immediate child of pwndSpb 00124 * on the path from pwndDirty to pwndSpb, so we can 00125 * subtract off the rectangles of the children of pwndSpb 00126 * in case there are intervening windows. 00127 */ 00128 while (pwndSpb != pwndDirtySave->spwndParent) { 00129 pwndDirtySave = pwndDirtySave->spwndParent; 00130 } 00131 00132 /* 00133 * The SubtractIntervening loop subtracts the 00134 * window rects starting from pwndSpb and ending 00135 * at the window before pwndDirty, so set up 00136 * our variables appropriately. 00137 */ 00138 pwndDirty = pwndDirtySave; 00139 pwndSpb = pwndSpb->spwndChild; 00140 00141 } else { 00142 /* 00143 * Now compare the Z order of pwndDirty and pwndSpb. 00144 * If pwndDirty is above pwndSpb, then the SPB can't be touched. 00145 */ 00146 pwndDirtySave = pwndDirty; 00147 00148 /* 00149 * Compare the Z order by searching starting at pwndDirty, 00150 * moving DOWN the Z order list. If we encounter pwndSpb, 00151 * then pwndDirty is ABOVE or EQUAL to pwndSpb. 00152 */ 00153 for ( ; pwndDirty != NULL; pwndDirty = pwndDirty->spwndNext) { 00154 if (pwndDirty == pwndSpb) { 00155 return FALSE; 00156 } 00157 } 00158 pwndDirty = pwndDirtySave; 00159 00160 /* 00161 * We don't want to subtract the SPB window itself 00162 */ 00163 pwndSpb = pwndSpb->spwndNext; 00164 } 00165 00166 /* 00167 * Subtract Intervening rectangles. 00168 * pwndDirty is below pwndSpb. If there are any intervening 00169 * windows, subtract their window rects from lprcDirty to see if pwndDirty 00170 * is obscured. 00171 */ 00172 while (pwndSpb && pwndSpb != pwndDirty) { 00173 /* 00174 * If this window has a region selected, hwndDirty may draw through 00175 * it even though it has a full rectangle! We can't subtract its 00176 * rect from the dirty rect in this case. 00177 */ 00178 if ( TestWF(pwndSpb, WFVISIBLE) && 00179 !pwndSpb->hrgnClip && 00180 !SubtractRect(lprcDirty, lprcDirty, &pwndSpb->rcWindow)) { 00181 00182 return FALSE; 00183 } 00184 00185 pwndSpb = pwndSpb->spwndNext; 00186 } 00187 00188 // fall through 00189 ProbablyTouch: 00190 00191 /* 00192 * If the rectangles don't intersect, there is no invalidation. 00193 * (we make this test relatively late because it's expensive compared 00194 * to the tests above). 00195 * Otherwise, *lprcDirty now has the area of bits not obscured 00196 * by intervening windows. 00197 */ 00198 00199 return IntersectRect(lprcDirty, lprcDirty, &pspb->rc); 00200 }

PSPB FindSpb PWND  pwnd  ) 
 

Definition at line 965 of file spb.c.

References tagSPB::flags, gpDispInfo, NULL, tagDISPLAYINFO::pspbFirst, tagSPB::pspbNext, SPB_LOCKUPDATE, and tagSPB::spwnd.

Referenced by OffsetChildren(), RestoreSpb(), xxxDrawDragRect(), xxxFreeWindow(), and zzzBltValidBits().

00967 { 00968 PSPB pspb; 00969 00970 /* 00971 * Walk through the list of save popup bits looking for a match on 00972 * window handle. 00973 */ 00974 for (pspb = gpDispInfo->pspbFirst; pspb != NULL; pspb = pspb->pspbNext) { 00975 00976 if (pspb->spwnd == pwnd && !(pspb->flags & SPB_LOCKUPDATE)) 00977 break; 00978 } 00979 00980 return pspb; 00981 }

VOID FreeAllSpbs void   ) 
 

Definition at line 1252 of file spb.c.

References AnySpbs, FreeSpb(), gpDispInfo, NULL, tagDISPLAYINFO::pspbFirst, and VOID().

Referenced by InitiateWin32kCleanup(), xxxRealizePalette(), xxxSetDeskWallpaper(), xxxSwitchDesktop(), and xxxUserChangeDisplaySettings().

01253 { 01254 01255 while(AnySpbs()) { 01256 FreeSpb(gpDispInfo->pspbFirst); 01257 } 01258 01259 gpDispInfo->pspbFirst = NULL; 01260 }

VOID FreeSpb PSPB  pspb  ) 
 

Definition at line 1171 of file spb.c.

References AnySpbs, ClrWF, tagDCE::DCX_flags, tagSPB::flags, gpDispInfo, tagSPB::hbm, tagDCE::hdc, tagDISPLAYINFO::hDev, tagSPB::hrgn, NULL, tagDISPLAYINFO::pdceFirst, tagDCE::pdceNext, tagDISPLAYINFO::pspbFirst, tagSPB::pspbNext, SPB_SAVESCREENBITS, tagSPB::spwnd, tagSPB::ulSaveId, Unlock, VOID(), and WFHASSPB.

Referenced by FreeAllSpbs(), LockWindowUpdate2(), RestoreSpb(), SpbCheckPwnd(), SpbCheckRect2(), xxxDrawDragRect(), xxxFreeWindow(), and zzzBltValidBits().

01173 { 01174 PSPB *ppspb; 01175 PDCE pdce; 01176 01177 if (pspb == NULL) 01178 return; 01179 01180 /* 01181 * Delete the bitmap. If saved in screen memory, make special call. 01182 */ 01183 if (pspb->flags & SPB_SAVESCREENBITS) { 01184 GreSaveScreenBits(gpDispInfo->hDev, SS_FREE, pspb->ulSaveId, NULL); 01185 } else if (pspb->hbm != NULL) { 01186 GreDeleteObject(pspb->hbm); 01187 } 01188 01189 /* 01190 * Destroy the region. 01191 */ 01192 if (pspb->hrgn != NULL){ 01193 GreDeleteObject(pspb->hrgn); 01194 } 01195 01196 /* 01197 * Forget that there is an attached SPB. 01198 */ 01199 if (pspb->spwnd != NULL) { 01200 ClrWF(pspb->spwnd, WFHASSPB); 01201 Unlock(&pspb->spwnd); 01202 } 01203 01204 /* 01205 * Unlink the spb. 01206 */ 01207 ppspb = &gpDispInfo->pspbFirst; 01208 while (*ppspb != pspb) { 01209 ppspb = &(*ppspb)->pspbNext; 01210 } 01211 01212 *ppspb = pspb->pspbNext; 01213 01214 /* 01215 * Free the save popup bits structure. 01216 */ 01217 UserFreePool(pspb); 01218 01219 /* 01220 * If we no longer have any SPBs then turn off window MGR 01221 * bounds collection. 01222 */ 01223 if (!AnySpbs()) { 01224 01225 GreLockDisplay(gpDispInfo->hDev); 01226 01227 /* 01228 * Reset the dirty areas of all of the DC's. NULL means reset. 01229 */ 01230 for (pdce = gpDispInfo->pdceFirst; pdce != NULL; pdce = pdce->pdceNext) { 01231 01232 if (pdce->DCX_flags & DCX_LAYERED) 01233 continue; 01234 01235 GreGetBounds(pdce->hdc, NULL, GGB_DISABLE_WINMGR); 01236 } 01237 01238 GreUnlockDisplay(gpDispInfo->hDev); 01239 } 01240 01241 }

BOOL LockWindowUpdate2 PWND  pwndLock,
BOOL  fThreadOverride
 

Definition at line 802 of file spb.c.

References BEGINATOMICCHECK, BOOL, CreateSpb(), DeferWinEventNotify, ENDATOMICCHECK, FALSE, tagSPB::flags, FreeSpb(), ghrgnSPB1, gpDispInfo, gptiLockUpdate, gspwndLockUpdate, tagDISPLAYINFO::hDev, tagSPB::hrgn, HRGN_FULL, IDC_DEFAULT, IsWinEventNotifyDeferredOK, Lock, NULL, tagDISPLAYINFO::pspbFirst, tagSPB::pspbNext, PtiCurrent, PUDF_LOCKFULLSCREEN, PWNDDESKTOP, tagSPB::rc, SetRectRgnIndirect(), SPB_LOCKUPDATE, SpbCheck(), SpbCheckPwnd(), SubtractRgn, TEST_PUDF, TRUE, Unlock, xxxInternalInvalidate(), zzzEndDeferWinEventNotify, and zzzInvalidateDCCache().

Referenced by FullScreenCleanup(), NtUserLockWindowUpdate(), xxxMakeWindowForegroundWithState(), xxxMS_TrackMove(), xxxProcessEventMessage(), and xxxSetForegroundWindow2().

00805 { 00806 PSPB pspb; 00807 BOOL fInval; 00808 HRGN hrgn; 00809 PTHREADINFO ptiCurrent = PtiCurrent(); 00810 00811 if ( /* 00812 * If we're full screen right now, fail this call. 00813 */ 00814 TEST_PUDF(PUDF_LOCKFULLSCREEN) 00815 00816 || 00817 00818 /* 00819 * If the screen is already locked, and it's being locked 00820 * by some other app, then fail. If fThreadOverride is set 00821 * then we're calling internally and it's okay to cancel 00822 * someone elses LockUpdate. 00823 */ 00824 ( gptiLockUpdate != NULL && 00825 gptiLockUpdate != PtiCurrent() && 00826 !fThreadOverride)) { 00827 UserAssert(IsWinEventNotifyDeferredOK()); 00828 00829 RIPERR0(ERROR_SCREEN_ALREADY_LOCKED, 00830 RIP_WARNING, 00831 "LockWindowUpdate failed because screen is locked by another application."); 00832 00833 return FALSE; 00834 } 00835 00836 if ((pwndLock != NULL) == (gptiLockUpdate != NULL)) { 00837 if (!fThreadOverride) { 00838 RIPERR1(ERROR_INVALID_PARAMETER, 00839 RIP_WARNING, 00840 "LockWindowUpdate failed because it is already %s.", 00841 (pwndLock != NULL) ? "locked" : "unlocked"); 00842 } 00843 00844 return FALSE; 00845 } 00846 00847 /* 00848 * This must be done while holding the screen critsec. 00849 * Deadlock if we callback during this, so defer WinEvent notifications 00850 */ 00851 DeferWinEventNotify(); 00852 GreLockDisplay(gpDispInfo->hDev); 00853 00854 if (pwndLock != NULL) { 00855 /* 00856 * We're about to make pwndLock and its siblings invisible: 00857 * go invalidate any other affected SPBs. 00858 */ 00859 SpbCheckPwnd(pwndLock); 00860 00861 CreateSpb(pwndLock, SPB_LOCKUPDATE, NULL); 00862 00863 Lock(&(gspwndLockUpdate), pwndLock); 00864 gptiLockUpdate = ptiCurrent; 00865 00866 zzzInvalidateDCCache(pwndLock, IDC_DEFAULT); 00867 00868 } else { 00869 /* 00870 * Flush any accumulated rectangles and invalidate spbs. 00871 */ 00872 SpbCheck(); 00873 00874 /* 00875 * Save this in a local before we set it to NULL 00876 */ 00877 pwndLock = gspwndLockUpdate; 00878 00879 gptiLockUpdate = NULL; 00880 Unlock(&gspwndLockUpdate); 00881 00882 zzzInvalidateDCCache(pwndLock, IDC_DEFAULT); 00883 00884 /* 00885 * Assume SPB doesn't exist, or couldn't be created, and that we 00886 * must invalidate the entire window. 00887 */ 00888 fInval = TRUE; 00889 hrgn = HRGN_FULL; 00890 00891 /* 00892 * Find the LOCKUPDATE spb in the list, and if present calculate 00893 * the area that has been invalidated, if any. 00894 */ 00895 for (pspb = gpDispInfo->pspbFirst; pspb != NULL; pspb = pspb->pspbNext) { 00896 00897 if (pspb->flags & SPB_LOCKUPDATE) { 00898 00899 if (pspb->hrgn == NULL) { 00900 00901 /* 00902 * If no invalid area, then no invalidation needed. 00903 */ 00904 fInval = FALSE; 00905 00906 } else { 00907 00908 /* 00909 * Subtract SPB valid region from SPB rectangle, to 00910 * yield invalid region. 00911 */ 00912 hrgn = ghrgnSPB1; 00913 SetRectRgnIndirect(hrgn, &pspb->rc); 00914 00915 /* 00916 * If spb rect minus the spb valid rgn is empty, 00917 * then there is nothing to invalidate. 00918 */ 00919 fInval = SubtractRgn(hrgn, hrgn, pspb->hrgn) != NULLREGION; 00920 } 00921 00922 FreeSpb(pspb); 00923 00924 /* 00925 * Exit this loop (there can be only one LOCKUPDATE spb) 00926 */ 00927 break; 00928 } 00929 } 00930 00931 if (fInval) { 00932 BEGINATOMICCHECK(); 00933 // want to prevent WinEvent notifies, but this make break asserts 00934 DeferWinEventNotify(); 00935 xxxInternalInvalidate(PWNDDESKTOP(pwndLock), 00936 hrgn, 00937 RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); 00938 zzzEndDeferWinEventNotify(); 00939 ENDATOMICCHECK(); 00940 } 00941 00942 /* 00943 * Invalidate any other SPBs affected by the fact that this window 00944 * and its children are being made visible. 00945 */ 00946 SpbCheckPwnd(pwndLock); 00947 } 00948 00949 GreUnlockDisplay(gpDispInfo->hDev); 00950 zzzEndDeferWinEventNotify(); 00951 00952 return TRUE; 00953 }

UINT RestoreSpb PWND  pwnd,
HRGN  hrgnUncovered,
HDC *  phdcScreen
 

Definition at line 651 of file spb.c.

References Error, FindSpb(), tagSPB::flags, FreeSpb(), ghdcMem, ghrgnSPB1, ghrgnSPB2, gpDispInfo, tagSPB::hbm, tagDISPLAYINFO::hdcScreen, tagDISPLAYINFO::hDev, tagSPB::hrgn, tagWND::hrgnClip, IntersectRgn, IsVisible(), NULL, tagSPB::rc, RSPB_INVALIDATE, RSPB_INVALIDATE_SSB, RSPB_NO_INVALIDATE, SetRectRgnIndirect(), SPB_SAVESCREENBITS, SubtractRgn, UINT, and tagSPB::ulSaveId.

Referenced by zzzBltValidBits().

00655 { 00656 PSPB pspb; 00657 UINT uInvalidate; 00658 HRGN hrgnRestorable; 00659 00660 /* 00661 * Note that we DON'T call SpbCheck() here -- 00662 * SpbCheck() is called by zzzBltValidBits(). 00663 */ 00664 pspb = FindSpb(pwnd); 00665 00666 /* 00667 * Assume all of hrgnUncovered was restored, and there's nothing 00668 * for our caller to invalidate. 00669 */ 00670 uInvalidate = RSPB_NO_INVALIDATE; 00671 hrgnRestorable = hrgnUncovered; 00672 00673 /* 00674 * First determine whether or not there is any area at all to restore. 00675 * If hrgnUncovered & pspb->hrgn is empty, then all of hrgnUncovered 00676 * needs to be invalidated, and there's nothing to restore. 00677 */ 00678 if (pspb->hrgn != NULL) { 00679 /* 00680 * At least some of hrgnUncovered needs to be invalidated. 00681 */ 00682 uInvalidate = RSPB_INVALIDATE; 00683 00684 /* 00685 * Calculate the true area of bits to be restored. If it becomes 00686 * empty, then just free the SPB without changing hrgnUncovered, 00687 * which is the area that must be invalidated. 00688 */ 00689 hrgnRestorable = ghrgnSPB1; 00690 switch (IntersectRgn(hrgnRestorable, hrgnUncovered, pspb->hrgn)) { 00691 case ERROR: 00692 case NULLREGION: 00693 goto Error; 00694 00695 default: 00696 break; 00697 } 00698 } 00699 00700 if (pspb->flags & SPB_SAVESCREENBITS) { 00701 00702 RECT rc = pspb->rc; 00703 00704 /* 00705 * Since the restore frees the onboard memory, clear this 00706 * bit so FreeSpb() won't try to free it again (regardless of 00707 * whether we get an error or not) 00708 */ 00709 pspb->flags &= ~SPB_SAVESCREENBITS; 00710 if (!(GreSaveScreenBits(gpDispInfo->hDev, 00711 SS_RESTORE, 00712 pspb->ulSaveId, 00713 (RECTL *)&rc))) { 00714 goto Error; 00715 } 00716 00717 /* 00718 * The SS_RESTORE call will always restore the entire SPB 00719 * rectangle, part of which may fall outside of hrgnUncovered. 00720 * The area that must be invalidated by our caller is simply 00721 * the SPB rectangle minus the area of restorable bits. 00722 * 00723 * If this region is not empty, then the SPB was not completely 00724 * restored, so we must return FALSE. 00725 */ 00726 SetRectRgnIndirect(ghrgnSPB2, &pspb->rc); 00727 if (SubtractRgn(hrgnUncovered, ghrgnSPB2, hrgnRestorable) != NULLREGION) { 00728 uInvalidate = RSPB_INVALIDATE_SSB; 00729 } 00730 } else { 00731 00732 HDC hdcScreen; 00733 HBITMAP hbmSave; 00734 00735 /* 00736 * In the unlikely event we need a screen DC and one wasn't passed in, 00737 * get it now. If we get one, we return the handle in *phdcScreen 00738 * so that our caller can release it later. 00739 */ 00740 if (!*phdcScreen) { 00741 *phdcScreen = gpDispInfo->hdcScreen; 00742 } 00743 00744 hdcScreen = *phdcScreen; 00745 00746 hbmSave = (HBITMAP)GreSelectBitmap(ghdcMem, pspb->hbm); 00747 if (!hbmSave) 00748 goto Error; 00749 00750 /* 00751 * Be sure to clip to the area of restorable bits. 00752 */ 00753 00754 GreSelectVisRgn(hdcScreen, hrgnRestorable, SVR_COPYNEW); 00755 00756 GreBitBlt(hdcScreen, 00757 pspb->rc.left, pspb->rc.top, 00758 pspb->rc.right - pspb->rc.left, 00759 pspb->rc.bottom - pspb->rc.top, 00760 ghdcMem, 00761 pspb->rc.left & 0x0007, 00762 0, 00763 SRCCOPY, 00764 0); 00765 00766 GreSelectBitmap(ghdcMem, hbmSave); 00767 00768 /* 00769 * Now compute the area to be invalidated for return. 00770 * This is simply the original hrgnUncovered - hrgnRestorable 00771 */ 00772 SubtractRgn(hrgnUncovered, hrgnUncovered, hrgnRestorable); 00773 } 00774 00775 if (pwnd->hrgnClip == NULL || !IsVisible(pwnd)) 00776 FreeSpb(pspb); 00777 00778 return uInvalidate; 00779 00780 Error: 00781 FreeSpb(pspb); 00782 return RSPB_INVALIDATE; 00783 }

VOID SpbCheck VOID   ) 
 

Definition at line 995 of file spb.c.

References AnySpbs, tagDCE::DCX_flags, gpDispInfo, tagDISPLAYINFO::hDev, NULL, tagDISPLAYINFO::pdceFirst, tagDCE::pdceNext, SpbCheckDce(), SpbCheckRect(), and VOID().

Referenced by CreateSpb(), LockWindowUpdate2(), and zzzBltValidBits().

00996 { 00997 PDCE pdce; 00998 RECT rcBounds; 00999 01000 if (AnySpbs()) { 01001 01002 GreLockDisplay(gpDispInfo->hDev); 01003 01004 /* 01005 * Walk through all of the DC's, accumulating dirty areas. 01006 */ 01007 for (pdce = gpDispInfo->pdceFirst; pdce != NULL; pdce = pdce->pdceNext) { 01008 01009 /* 01010 * Only check valid cache entries... 01011 */ 01012 if (pdce->DCX_flags & (DCX_INVALID | DCX_DESTROYTHIS)) 01013 continue; 01014 01015 SpbCheckDce(pdce); 01016 } 01017 01018 /* 01019 * Subtact out DirectDraw dirty rect from all the SPB's. The call to 01020 * GreGetDirectDrawBounds will also reset the accumulated bounds. 01021 */ 01022 if (GreGetDirectDrawBounds(gpDispInfo->hDev, &rcBounds)) { 01023 SpbCheckRect(NULL, &rcBounds, 0); 01024 } 01025 01026 GreUnlockDisplay(gpDispInfo->hDev); 01027 } 01028 }

VOID SpbCheckDce PDCE  pdce  ) 
 

Definition at line 1040 of file spb.c.

References tagDCE::DCX_flags, tagDCE::hdc, IntersectRect(), NULL, OffsetRect(), tagDCE::pMonitor, tagDCE::pwndOrg, tagMONITOR::rcMonitor, SpbCheckRect(), and VOID().

Referenced by _GetDCEx(), GetMonitorDC(), InvalidateDce(), and SpbCheck().

01042 { 01043 RECT rc; 01044 01045 if (pdce->DCX_flags & DCX_LAYERED) 01046 return; 01047 01048 /* 01049 * Query the dirty bounds rectangle. Doing this clears the bounds 01050 * as well. 01051 */ 01052 if (GreGetBounds(pdce->hdc, &rc, 0)) { 01053 01054 if (pdce->pMonitor != NULL) { 01055 /* 01056 * Convert the bounds rect to screen coords. 01057 */ 01058 OffsetRect(&rc, pdce->pMonitor->rcMonitor.left, 01059 pdce->pMonitor->rcMonitor.top); 01060 } 01061 01062 /* 01063 * Intersect the returned rectangle with the window rectangle 01064 * in case the guy was drawing outside his window 01065 */ 01066 if (IntersectRect(&rc, &rc, &(pdce->pwndOrg)->rcWindow)) 01067 SpbCheckRect(pdce->pwndOrg, &rc, pdce->DCX_flags); 01068 } 01069 }

VOID SpbCheckPwnd PWND  pwnd  ) 
 

Definition at line 1126 of file spb.c.

References FreeSpb(), gpDispInfo, NULL, tagDISPLAYINFO::pspbFirst, tagSPB::pspbNext, tagWND::rcWindow, SpbCheckRect(), tagSPB::spwnd, tagWND::spwndParent, and VOID().

Referenced by LockWindowUpdate2(), and xxxDWP_SetRedraw().

01128 { 01129 PSPB pspb; 01130 PWND pwndSpb; 01131 PSPB pspbNext; 01132 01133 /* 01134 * First blow away any SPBs owned by this window or its children. 01135 */ 01136 for (pspb = gpDispInfo->pspbFirst; pspb != NULL; pspb = pspbNext) { 01137 01138 /* 01139 * Get pspbNext now in case we free the SPB 01140 */ 01141 pspbNext = pspb->pspbNext; 01142 01143 /* 01144 * If pspb->spwnd is == pwnd or a child of pwnd, then free the SPB 01145 */ 01146 for (pwndSpb = pspb->spwnd; pwndSpb; pwndSpb = pwndSpb->spwndParent) { 01147 01148 if (pwnd == pwndSpb) 01149 FreeSpb(pspb); 01150 } 01151 } 01152 01153 /* 01154 * Then see if any other SPBs are affected... 01155 */ 01156 if (gpDispInfo->pspbFirst != NULL) { 01157 SpbCheckRect(pwnd, &pwnd->rcWindow, 0); 01158 } 01159 }

VOID SpbCheckRect PWND  pwnd,
LPRECT  lprc,
DWORD  flags
 

Definition at line 1081 of file spb.c.

References gpDispInfo, IsVisible(), NULL, tagDISPLAYINFO::pspbFirst, tagSPB::pspbNext, SpbCheckRect2(), and VOID().

Referenced by _ScrollDC(), BltValidInit(), SpbCheck(), SpbCheckDce(), SpbCheckPwnd(), xxxInternalInvalidate(), xxxScrollWindowEx(), and zzzBltValidBits().

01085 { 01086 PSPB pspb, pspbNext; 01087 01088 /* 01089 * If this window isn't visible, we're done. 01090 */ 01091 if (!IsVisible(pwnd)) 01092 return; 01093 01094 for (pspb = gpDispInfo->pspbFirst; pspb != NULL; pspb = pspbNext) { 01095 01096 /* 01097 * Get the pointer to the next save popup bits structure now 01098 * in case SpbCheckRect2() frees the current one. 01099 */ 01100 pspbNext = pspb->pspbNext; 01101 01102 /* 01103 * In win3.1 they used to exit the function if this function 01104 * returned false. This meant that if one of the spbs was freed 01105 * the rest of the spbs would not be invalidated. 01106 */ 01107 SpbCheckRect2(pspb, pwnd, lprc, flags); 01108 } 01109 }

BOOL SpbCheckRect2 PSPB  pspb,
PWND  pwnd,
LPRECT  lprc,
DWORD  flags
 

Definition at line 214 of file spb.c.

References BOOL, Error, FALSE, FBitsTouch(), FreeSpb(), ghrgnSCR, tagSPB::hrgn, tagSPB::rc, SetOrCreateRectRgnIndirectPublic(), SetRectRgnIndirect(), SubtractRgn, and TRUE.

Referenced by SpbCheckRect(), and SpbTransfer().

00219 { 00220 RECT rcTouch = *lprc; 00221 00222 /* 00223 * See if lprc touches any saved bits, taking into account what 00224 * window the drawing is occuring in. 00225 */ 00226 if (FBitsTouch(pwnd, &rcTouch, pspb, flags)) { 00227 00228 /* 00229 * If no SPB region exists, make one for the whole thing 00230 */ 00231 if (!pspb->hrgn && SetOrCreateRectRgnIndirectPublic( 00232 &pspb->hrgn, &pspb->rc) == ERROR) { 00233 00234 goto Error; 00235 } 00236 00237 /* 00238 * Subtract the rectangle that is invalid from the SPB region 00239 */ 00240 SetRectRgnIndirect(ghrgnSCR, &rcTouch); 00241 switch (SubtractRgn(pspb->hrgn, pspb->hrgn, ghrgnSCR)) { 00242 case ERROR: 00243 case NULLREGION: 00244 goto Error; 00245 00246 default: 00247 break; 00248 } 00249 } 00250 00251 return TRUE; 00252 00253 Error: 00254 FreeSpb(pspb); 00255 return FALSE; 00256 }

BOOL SpbTransfer PSPB  pspb,
PWND  pwnd,
BOOL  fChildren
 

Definition at line 273 of file spb.c.

References BEGINATOMICCHECK, BOOL, ENDATOMICCHECK, FALSE, ghrgnSPB2, HRGN_FULL, tagWND::hrgnUpdate, IntersectWithParents(), NULL, tagWND::rcWindow, SpbCheckRect2(), tagWND::spwndChild, tagWND::spwndNext, TRUE, and xxxInternalInvalidate().

Referenced by CreateSpb().

00277 { 00278 RECT rc; 00279 00280 /* 00281 * If the window has an update region... 00282 */ 00283 if (pwnd->hrgnUpdate != NULL) { 00284 00285 /* 00286 * Invalidate its update region rectangle from the SPB 00287 */ 00288 if (pwnd->hrgnUpdate > HRGN_FULL) { 00289 GreGetRgnBox(pwnd->hrgnUpdate, &rc); 00290 } else { 00291 rc = pwnd->rcWindow; 00292 } 00293 00294 /* 00295 * Intersect the update region bounds with the parent client rects, 00296 * to make sure we don't invalidate more than we need to. If 00297 * nothing to validate, return TRUE (because SPB is probably not empty) 00298 * These RDW_ flags won't cause the critical section to be left, nor 00299 * will they provoke WinEvent notifications. 00300 */ 00301 if (IntersectWithParents(pwnd, &rc)) { 00302 BEGINATOMICCHECK(); 00303 00304 xxxInternalInvalidate(pwnd, 00305 ghrgnSPB2, 00306 RDW_VALIDATE | RDW_NOCHILDREN); 00307 00308 ENDATOMICCHECK(); 00309 00310 /* 00311 * If the SPB vanished, return FALSE. 00312 */ 00313 if (!SpbCheckRect2(pspb, pwnd, &rc, DCX_WINDOW)) 00314 return FALSE; 00315 } 00316 } 00317 00318 if (fChildren) { 00319 for (pwnd = pwnd->spwndChild; pwnd != NULL; pwnd = pwnd->spwndNext) { 00320 if (!SpbTransfer(pspb, pwnd, TRUE)) { 00321 return FALSE; 00322 } 00323 } 00324 } 00325 00326 return TRUE; 00327 }


Generated on Sat May 15 19:45:39 2004 for test by doxygen 1.3.7