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

swp.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define CTM_NOCHANGE   0
#define CTM_TOPMOST   1
#define CTM_NOTOPMOST   2
#define DBGCheskSMWP(psmwp)
#define MW_FLAGS_REDRAW   (SWP_NOZORDER | SWP_NOACTIVATE)
#define MW_FLAGS_NOREDRAW   (SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW)
#define rcWindowNew   params.rgrc[0]
#define rcWindowOld   params.rgrc[1]
#define rcClientOld   params.rgrc[2]
#define rcClientNew   params.rgrc[0]
#define rcValidDst   params.rgrc[1]
#define rcValidSrc   params.rgrc[2]
#define SWP_BOZO   ( SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE )
#define DBGValidateSibblingZOrder(pwndParent)
#define SWR_FLAGS_REDRAW   (SWP_NOCHANGE | SWP_FRAMECHANGED | SWP_NOACTIVATE)
#define SWR_FLAGS_NOREDRAW   (SWP_NOCHANGE | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREDRAW)
#define SLOP_X   8
#define SLOP_Y   8

Functions

void FixBogusSWP (PWND pwnd, int *px, int *py, int cx, int cy, UINT flags)
void PreventInterMonitorBlts (PCVR pcvr)
void DestroySMWP (PSMWP psmwp)
BOOL xxxMoveWindow (PWND pwnd, int x, int y, int cx, int cy, BOOL fRedraw)
BOOL AllocateCvr (PSMWP psmwp, int cwndHint)
PSMWP InternalBeginDeferWindowPos (int cwndHint)
PSMWP _BeginDeferWindowPos (int cwndHint)
PWND PWInsertAfter (HWND hwnd)
HWND HWInsertAfter (PWND pwnd)
PSMWP _DeferWindowPos (PSMWP psmwp, PWND pwnd, PWND pwndInsertAfter, int x, int y, int cx, int cy, UINT flags)
BOOL ValidateWindowPos (PCVR pcvr, PWND pwndParent)
BOOL IsStillWindowC (HWND hwndc)
BOOL ValidateSmwp (PSMWP psmwp, BOOL *pfSyncPaint)
PWINDOWPOS FindValidWindowPos (PSMWP psmwp)
PWND GetLastNonBottomMostWindow (PWND pwnd, BOOL fSkipSelf)
BOOL ValidateZorder (PCVR pcvr)
BOOL xxxCalcValidRects (PSMWP psmwp, HWND *phwndNewActive)
PWND GetLastTopMostWindow (VOID)
BOOL xxxSetWindowPos (PWND pwnd, PWND pwndInsertAfter, int x, int y, int cx, int cy, UINT flags)
BOOL xxxSwpActivate (PWND pwndNewActive)
VOID xxxSendChangedMsgs (PSMWP psmwp)
void AsyncWindowPos (PSMWP psmwp)
VOID xxxProcessSetWindowPosEvent (PSMWP psmwpT)
VOID zzzChangeStates (PWND pwndParent, PSMWP psmwp)
BOOL SwpCalcVisRgn (PWND pwnd, HRGN hrgn)
BOOL CombineOldNewVis (HRGN hrgn, HRGN hrgnVisOld, HRGN hrgnVisNew, UINT crgn, UINT fsRgnEmpty)
int BltValidInit (PSMWP psmwp)
BOOL zzzBltValidBits (PSMWP psmwp)
VOID xxxHandleWindowPosChanged (PWND pwnd, PWINDOWPOS ppos)
PWND GetRealOwner (PWND pwnd)
PWND NextOwnedWindow (PWND pwnd, PWND pwndOwner, PWND pwndParent)
VOID SetTopmost (PWND pwndRoot, BOOL fTopmost)
PWND CalcForegroundInsertAfter (PWND pwnd)
PWND GetTopMostInsertAfter (PWND pwnd)
int CheckTopmost (PWINDOWPOS ppos)
BOOL IsOwnee (PWND pwndOwnee, PWND pwndOwner)
BOOL IsBehind (PWND pwnd, PWND pwndReference)
PSMWP AddSelfAndOwnees (PSMWP psmwp, PWND pwnd, PWND pwndChange, PWND pwndInsertAfter, int iTop)
PSMWP ZOrderByOwner2 (PSMWP psmwp, int iTop)
BOOL TrackBackground (WINDOWPOS *ppos, PWND pwndPrev, PWND pwnd)
void TrackZorderHelper (WINDOWPOS *ppos, HWND *phwnd)
PWND TrackZorder (WINDOWPOS *ppos, PWND pwndPrev, HWND *phwndTop, HWND *phwndReg)
PSMWP ZOrderByOwner (PSMWP psmwp)
BOOL xxxEndDeferWindowPosEx (PSMWP psmwp, BOOL fAsync)
BOOL FVisCountable (PWND pwnd)
VOID IncVisWindows (PWND pwnd)
__inline void cDecVis (PWND pwnd)
VOID DecVisWindows (PWND pwnd)
VOID SetMinimize (PWND pwnd, UINT uFlags)
VOID SetVisible (PWND pwnd, UINT flags)
BOOL IsMaxedRect (LPRECT lprcWithin, PCSIZERECT psrcMaybe)
BOOL xxxCheckFullScreen (PWND pwnd, PSIZERECT psrc)
VOID ClrFTrueVis (PWND pwnd)
VOID OffsetChildren (PWND pwnd, int dx, int dy, LPRECT prcHitTest)
BOOL xxxSetWindowRgn (PWND pwnd, HRGN hrgn, BOOL fRedraw)
void SelectWindowRgn (PWND pwnd, HRGN hrgnClip)
BOOL TestRectBogus (RECT *prc, int x, int y, int cx, int cy)
BOOL IsRectBogus (int x, int y, int cx, int cy)


Define Documentation

#define CTM_NOCHANGE   0
 

Definition at line 17 of file swp.c.

Referenced by CheckTopmost(), and ZOrderByOwner().

#define CTM_NOTOPMOST   2
 

Definition at line 19 of file swp.c.

Referenced by CheckTopmost(), and ZOrderByOwner().

#define CTM_TOPMOST   1
 

Definition at line 18 of file swp.c.

Referenced by CheckTopmost(), and ZOrderByOwner().

#define DBGCheskSMWP psmwp   ) 
 

Definition at line 52 of file swp.c.

Referenced by _BeginDeferWindowPos(), _DeferWindowPos(), DestroySMWP(), InternalBeginDeferWindowPos(), and xxxEndDeferWindowPosEx().

#define DBGValidateSibblingZOrder pwndParent   ) 
 

Definition at line 1945 of file swp.c.

#define MW_FLAGS_NOREDRAW   (SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW)
 

Definition at line 142 of file swp.c.

Referenced by xxxMoveWindow().

#define MW_FLAGS_REDRAW   (SWP_NOZORDER | SWP_NOACTIVATE)
 

Definition at line 141 of file swp.c.

Referenced by xxxMoveWindow().

#define rcClientNew   params.rgrc[0]
 

Referenced by xxxCalcValidRects().

#define rcClientOld   params.rgrc[2]
 

Referenced by xxxCalcValidRects().

#define rcValidDst   params.rgrc[1]
 

Referenced by xxxCalcValidRects().

#define rcValidSrc   params.rgrc[2]
 

Referenced by xxxCalcValidRects().

#define rcWindowNew   params.rgrc[0]
 

Referenced by xxxCalcValidRects().

#define rcWindowOld   params.rgrc[1]
 

Referenced by xxxCalcValidRects().

#define SLOP_X   8
 

Definition at line 5838 of file swp.c.

Referenced by TestRectBogus().

#define SLOP_Y   8
 

Definition at line 5839 of file swp.c.

Referenced by TestRectBogus().

#define SWP_BOZO   ( SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE )
 

Definition at line 1916 of file swp.c.

Referenced by zzzChangeStates().

#define SWR_FLAGS_NOREDRAW   (SWP_NOCHANGE | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREDRAW)
 

Definition at line 5659 of file swp.c.

Referenced by xxxSetWindowRgn().

#define SWR_FLAGS_REDRAW   (SWP_NOCHANGE | SWP_FRAMECHANGED | SWP_NOACTIVATE)
 

Definition at line 5658 of file swp.c.

Referenced by xxxSetWindowRgn().


Function Documentation

PSMWP _BeginDeferWindowPos int  cwndHint  ) 
 

Definition at line 272 of file swp.c.

References AllocateCvr(), tagSMWP::bHandle, DBGCheskSMWP, HMAllocObject(), HMFreeObject(), NULL, PtiCurrent, TRUE, and TYPE_SETWINDOWPOS.

00273 { 00274 PSMWP psmwp; 00275 00276 psmwp = (PSMWP)HMAllocObject(PtiCurrent(), NULL, TYPE_SETWINDOWPOS, sizeof(SMWP)); 00277 if (psmwp == NULL) { 00278 return NULL; 00279 } 00280 00281 if (cwndHint == 0) { 00282 cwndHint = 8; 00283 } 00284 00285 if (!AllocateCvr(psmwp, cwndHint)) { 00286 HMFreeObject(psmwp); 00287 return NULL; 00288 } 00289 00290 psmwp->bHandle = TRUE; 00291 DBGCheskSMWP(psmwp); 00292 return psmwp; 00293 }

PSMWP _DeferWindowPos PSMWP  psmwp,
PWND  pwnd,
PWND  pwndInsertAfter,
int  x,
int  y,
int  cx,
int  cy,
UINT  flags
 

Definition at line 365 of file swp.c.

References tagSMWP::acvr, tagSMWP::ccvr, tagSMWP::ccvrAlloc, CVR, cy, DBGCheskSMWP, DestroySMWP(), DWORD, tagCVR::hrgnClip, tagCVR::hrgnInterMonitor, HWInsertAfter(), HWq, NULL, tagCVR::pos, ppos, TestWF, and WFBOTTOMMOST.

Referenced by AddSelfAndOwnees(), NtUserDeferWindowPos(), xxxArrangeIconicWindows(), xxxDesktopRecalc(), xxxMinMaximize(), xxxSetWindowPos(), and xxxSetWindowRgn().

00374 { 00375 PWINDOWPOS ppos; 00376 PCVR pcvr; 00377 00378 DBGCheskSMWP(psmwp); 00379 if (psmwp->ccvr + 1 > psmwp->ccvrAlloc) { 00380 00381 /* 00382 * Make space for 4 more windows 00383 */ 00384 DWORD dwNewAlloc = psmwp->ccvrAlloc + 4; 00385 00386 pcvr = (PCVR)UserReAllocPoolWithQuota(psmwp->acvr, 00387 psmwp->ccvrAlloc * sizeof(CVR), 00388 sizeof(CVR) * dwNewAlloc, 00389 TAG_SWP); 00390 00391 if (pcvr == NULL) { 00392 DestroySMWP(psmwp); 00393 return NULL; 00394 } 00395 00396 psmwp->acvr = pcvr; 00397 psmwp->ccvrAlloc = dwNewAlloc; 00398 } 00399 00400 pcvr = &psmwp->acvr[psmwp->ccvr++]; 00401 ppos = &pcvr->pos; 00402 00403 ppos->hwnd = HWq(pwnd); 00404 ppos->hwndInsertAfter = (TestWF(pwnd, WFBOTTOMMOST)) ? 00405 HWND_BOTTOM : HWInsertAfter(pwndInsertAfter); 00406 ppos->x = x; 00407 ppos->y = y; 00408 ppos->cx = cx; 00409 ppos->cy = cy; 00410 ppos->flags = flags; 00411 00412 pcvr->hrgnClip = NULL; 00413 pcvr->hrgnInterMonitor = NULL; 00414 00415 return psmwp; 00416 }

PSMWP AddSelfAndOwnees PSMWP  psmwp,
PWND  pwnd,
PWND  pwndChange,
PWND  pwndInsertAfter,
int  iTop
 

Definition at line 4191 of file swp.c.

References _DeferWindowPos(), tagSMWP::acvr, BOOL, tagSMWP::ccvr, FALSE, GetRealOwner(), IsBehind(), NextOwnedWindow(), NULL, tagCVR::pos, tagWND::spwndParent, and TRUE.

Referenced by ZOrderByOwner2().

04197 { 04198 PWND pwndChgOwnee; 04199 PWND pwndT; 04200 BOOL fChgOwneeInserted; 04201 CVR *pcvr; 04202 04203 /* 04204 * The general idea here is to first add our ownees, then add ourself. 04205 * When we add our ownees though, we add them as appropriate based 04206 * on the pwndInsertAfter parameter. 04207 * 04208 * Find out if any of our ownees are on a direct path between pwndChange 04209 * and the root of the owner tree. If one is, then its Z order relative 04210 * to its owner-siblings will be changing. If none are, then 04211 * we want to add our ownees to the list in their current order. 04212 */ 04213 pwndChgOwnee = pwndChange; 04214 while (pwndChgOwnee != NULL) { 04215 04216 pwndT = GetRealOwner(pwndChgOwnee); 04217 04218 if (pwnd == pwndT) 04219 break; 04220 04221 pwndChgOwnee = pwndT; 04222 } 04223 04224 /* 04225 * Now enumerate all other ownees, and insert them in their 04226 * current order. 04227 */ 04228 fChgOwneeInserted = FALSE; 04229 pwndT = NULL; 04230 while ((pwndT = NextOwnedWindow(pwndT, pwnd, pwnd->spwndParent)) != NULL) { 04231 04232 /* 04233 * If these siblings are to be reordered, compare the sibling's 04234 * current Z order with pwndInsertAfter. 04235 */ 04236 if (pwndChgOwnee == NULL) { 04237 04238 /* 04239 * No Z change for our ownees: just add them in their current order 04240 */ 04241 psmwp = AddSelfAndOwnees(psmwp, pwndT, NULL, NULL, iTop); 04242 04243 } else { 04244 04245 /* 04246 * If we haven't already inserted the ChgOwnee, and the 04247 * enumerated owner-sibling is behind pwndInsertAfter, then 04248 * add ChgOwnee. 04249 */ 04250 if (!fChgOwneeInserted && IsBehind(pwndT, pwndInsertAfter)) { 04251 04252 psmwp = AddSelfAndOwnees(psmwp, 04253 pwndChgOwnee, 04254 pwndChange, 04255 pwndInsertAfter, 04256 iTop); 04257 04258 if (psmwp == NULL) 04259 return NULL; 04260 04261 fChgOwneeInserted = TRUE; 04262 } 04263 04264 if (pwndT != pwndChgOwnee) { 04265 04266 /* 04267 * Not the change ownee: add it in its current order. 04268 */ 04269 psmwp = AddSelfAndOwnees(psmwp, pwndT, NULL, NULL, iTop); 04270 } 04271 } 04272 04273 if (psmwp == NULL) 04274 return NULL; 04275 } 04276 04277 /* 04278 * If we never added the change ownee in the loop, add it now. 04279 */ 04280 if ((pwndChgOwnee != NULL) && !fChgOwneeInserted) { 04281 04282 psmwp = AddSelfAndOwnees(psmwp, 04283 pwndChgOwnee, 04284 pwndChange, 04285 pwndInsertAfter, 04286 iTop); 04287 04288 if (psmwp == NULL) 04289 return NULL; 04290 } 04291 04292 /* 04293 * Finally, add this window to the list. 04294 */ 04295 psmwp = _DeferWindowPos(psmwp, pwnd, NULL, 04296 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 04297 04298 if (psmwp == NULL) 04299 return NULL; 04300 04301 /* 04302 * If we aren't inserting the topmost entry, 04303 * link this entry to the previous one. 04304 * The topmost entry will get set by our caller. 04305 */ 04306 if (iTop != psmwp->ccvr - 1) { 04307 pcvr = &psmwp->acvr[psmwp->ccvr - 1]; 04308 pcvr->pos.hwndInsertAfter = (pcvr - 1)->pos.hwnd; 04309 } 04310 return psmwp; 04311 }

BOOL AllocateCvr PSMWP  psmwp,
int  cwndHint
 

Definition at line 203 of file swp.c.

References tagSMWP::acvr, BOOL, tagSMWP::ccvr, tagSMWP::ccvrAlloc, FALSE, NULL, and TRUE.

Referenced by _BeginDeferWindowPos(), InternalBeginDeferWindowPos(), and Win32UserInitialize().

00204 { 00205 PCVR acvr; 00206 00207 UserAssert(cwndHint != 0); 00208 acvr = (PCVR)UserAllocPoolWithQuota(sizeof(CVR) * cwndHint, TAG_SWP); 00209 00210 if (acvr == NULL) { 00211 return FALSE; 00212 } 00213 00214 /* 00215 * Initialize psmwp related fields. 00216 * CVR array is initialized by _DeferWindowPos 00217 */ 00218 00219 psmwp->acvr = acvr; 00220 psmwp->ccvrAlloc = cwndHint; 00221 psmwp->ccvr = 0; 00222 return TRUE; 00223 }

void AsyncWindowPos PSMWP  psmwp  ) 
 

Definition at line 1753 of file swp.c.

References tagSMWP::acvr, BOOL, tagSMWP::ccvr, FALSE, NULL, PBYTE, tagCVR::pos, PostEventMessage(), tagTHREADINFO::pq, tagCVR::pti, PtiCurrent, QEVENT_SETWINDOWPOS, SMWP, and TRUE.

Referenced by xxxEndDeferWindowPosEx().

01755 { 01756 BOOL fFinished; 01757 PCVR pcvrFirst; 01758 PCVR pcvr; 01759 PCVR pcvrT; 01760 int ccvrRemaining; 01761 int ccvr; 01762 int chwnd; 01763 PTHREADINFO ptiT; 01764 PTHREADINFO ptiCurrent; 01765 PSMWP psmwpNew; 01766 01767 pcvrFirst = psmwp->acvr; 01768 ccvrRemaining = psmwp->ccvr; 01769 01770 ptiCurrent = PtiCurrent(); 01771 01772 while (TRUE) { 01773 01774 fFinished = TRUE; 01775 01776 /* 01777 * Loop through all windows in the SMWP list searching for windows 01778 * owned by other threads. Return if none are found. 01779 */ 01780 for (; ccvrRemaining != 0; pcvrFirst++, ccvrRemaining--) { 01781 01782 if (pcvrFirst->pos.hwnd == NULL) 01783 continue; 01784 01785 ptiT = pcvrFirst->pti; 01786 if (ptiT->pq != ptiCurrent->pq) { 01787 fFinished = FALSE; 01788 break; 01789 } 01790 } 01791 01792 if (fFinished) { 01793 return; 01794 } 01795 01796 /* 01797 * We've found a window of another thread. Count how many other 01798 * windows in the list are owned by the same thread so we can 01799 * allocate a CVR array for them. 01800 */ 01801 chwnd = 0; 01802 01803 for (pcvr = pcvrFirst, ccvr = ccvrRemaining; --ccvr >= 0; pcvr++) { 01804 01805 if (pcvr->pos.hwnd == NULL) 01806 continue; 01807 01808 if (pcvr->pti->pq == ptiT->pq) 01809 chwnd++; 01810 } 01811 01812 /* 01813 * Allocate temp SMWP/CVR structure to be passed to the other thread. 01814 */ 01815 psmwpNew = (PSMWP)UserAllocPool(sizeof(SMWP) + (sizeof(CVR) * chwnd), 01816 TAG_SWP); 01817 01818 /* 01819 * Even if we can't allocate memory to pass the SMWP to another 01820 * thread we still need to remove its windows from the current list. 01821 */ 01822 if (psmwpNew == NULL) { 01823 01824 for (pcvr = pcvrFirst; chwnd != 0; pcvr++) { 01825 01826 if (pcvr->pti->pq == ptiT->pq) { 01827 pcvr->pos.hwnd = NULL; 01828 chwnd--; 01829 } 01830 } 01831 01832 continue; 01833 } 01834 01835 psmwpNew->ccvr = chwnd; 01836 psmwpNew->acvr = (PCVR)((PBYTE)psmwpNew + sizeof(SMWP)); 01837 01838 for (pcvr = pcvrFirst, pcvrT = psmwpNew->acvr; chwnd != 0; pcvr++) { 01839 01840 if (pcvr->pos.hwnd == NULL) 01841 continue; 01842 01843 /* 01844 * Copy the appropriate CVR structs into our temp array. 01845 */ 01846 if (pcvr->pti->pq == ptiT->pq) { 01847 01848 *pcvrT++ = *pcvr; 01849 chwnd--; 01850 01851 /* 01852 * Remove this window from the list of windows to be handled 01853 * by the current thread. 01854 */ 01855 pcvr->pos.hwnd = NULL; 01856 } 01857 } 01858 01859 /* 01860 * This lets the other thread know it needs to do some windowposing. 01861 * The other thread is responsible for freeing the temp SMWP/CVR array. 01862 */ 01863 if (!PostEventMessage(ptiT, ptiT->pq, QEVENT_SETWINDOWPOS, NULL, 0, 01864 (WPARAM)psmwpNew, (LPARAM)ptiT)) { 01865 // IANJA RIP only to catch what was previously a bug: psmwpNew not freed 01866 RIPMSG1(RIP_WARNING, "PostEventMessage swp to pti %#p failed", ptiT); 01867 UserFreePool(psmwpNew); 01868 } 01869 } 01870 01871 }

int BltValidInit PSMWP  psmwp  ) 
 

Definition at line 2529 of file swp.c.

References tagSMWP::acvr, AnySpbs, BOOL, tagSMWP::ccvr, CreateEmptyRgn(), FALSE, tagCVR::fsRE, tagCVR::hrgnVisOld, IsStillWindowC(), NULL, tagCVR::pos, PreventInterMonitorBlts(), tagWND::rcWindow, RE_VISOLD, RevalidateHwnd, SpbCheckRect(), SwpCalcVisRgn(), SYSMET, TRUE, and UINT.

Referenced by zzzBltValidBits().

02531 { 02532 int ccvr; 02533 int cIter = 0; 02534 PCVR pcvr; 02535 PWND pwnd; 02536 BOOL fChangeState = FALSE; 02537 02538 /* 02539 * Before we change any window state, calculate the old visrgn 02540 */ 02541 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 02542 02543 UINT flags = pcvr->pos.flags; 02544 02545 /* 02546 * Make sure this is initialized to NULL; we may be sticking something 02547 * in it, and we want to know later if we need to free that thing. 02548 */ 02549 pcvr->hrgnVisOld = NULL; 02550 02551 if (pcvr->pos.hwnd == NULL) 02552 continue; 02553 02554 pwnd = RevalidateHwnd(pcvr->pos.hwnd); 02555 02556 if ((pwnd == NULL) || !IsStillWindowC(pcvr->pos.hwndInsertAfter)) { 02557 pcvr->pos.hwnd = NULL; 02558 pcvr->pos.flags = SWP_NOREDRAW | SWP_NOCHANGE; 02559 continue; 02560 } 02561 02562 /* 02563 * Before we change any window's state, ensure that any SPBs 02564 * over the window's old location are invalidated if necessary. 02565 * This must be done because no WM_PAINT messages will be 02566 * sent to anyone for the covered area if the area is obscured 02567 * by other windows. 02568 */ 02569 if (AnySpbs() && !(flags & SWP_NOREDRAW)) 02570 SpbCheckRect(pwnd, &pwnd->rcWindow, DCX_WINDOW); 02571 02572 /* 02573 * Count the number of passes through the loop 02574 */ 02575 cIter++; 02576 02577 /* 02578 * Remember if any SWPs need their state changed. 02579 */ 02580 if ((flags & SWP_CHANGEMASK) != SWP_NOCHANGE) 02581 fChangeState = TRUE; 02582 02583 /* 02584 * If we're not redrawing, no need to calculate visrgn 02585 */ 02586 if (pcvr->pos.flags & SWP_NOREDRAW) 02587 continue; 02588 02589 if (!SYSMET(SAMEDISPLAYFORMAT)) 02590 PreventInterMonitorBlts(pcvr); 02591 02592 pcvr->fsRE = 0; 02593 pcvr->hrgnVisOld = CreateEmptyRgn(); 02594 02595 if (pcvr->hrgnVisOld == NULL || 02596 !SwpCalcVisRgn(pwnd, pcvr->hrgnVisOld)) { 02597 02598 pcvr->fsRE = RE_VISOLD; 02599 } 02600 } 02601 02602 return (fChangeState ? cIter : 0); 02603 }

PWND CalcForegroundInsertAfter PWND  pwnd  ) 
 

Definition at line 3620 of file swp.c.

References FALSE, GetLastNonBottomMostWindow(), GetLastTopMostWindow(), GETPTI, gpqForeground, IS_IME_ENABLED, NULL, tagQ::spwndActive, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndOwner, tagWND::spwndParent, TestWF, TestwndChild, TIF_ALLOWFOREGROUNDACTIVATE, TRUE, WEFTOPMOST, WFBOTTOMMOST, and WFVISIBLE.

Referenced by CheckOnTop(), CheckTopmost(), TrackBackground(), xxxCreateWindowEx(), and xxxSetParent().

03622 { 03623 PWND pwndInsertAfter, pwndInsertAfterSave; 03624 PWND pwndT; 03625 PTHREADINFO ptiTop; 03626 #ifdef LATER // see #88810 03627 BOOLEAN fImeOwnerIsBottom = FALSE; 03628 #endif 03629 03630 /* 03631 * If we're allowing this application to make this top 03632 * level window foreground active, then this app may 03633 * not be foreground yet, but we want any windows it 03634 * zorders to appear on top because it is probably about 03635 * to activate them (this is a guess!) If this is the case, 03636 * let it do what it wants. A good example of this is an 03637 * application like toolbook that creates a window without a 03638 * caption, doesn't activate it, and wants that to appear on top. 03639 */ 03640 03641 if (TestWF(pwnd, WFBOTTOMMOST)) { 03642 pwndInsertAfter = GetLastNonBottomMostWindow(pwnd, TRUE); 03643 } else { 03644 pwndInsertAfter = GetLastTopMostWindow(); 03645 #ifdef LATER // see #88810 03646 if (IS_IME_ENABLED()) { 03647 fImeOwnerIsBottom = IsBottomIMEWindow(pwnd); 03648 if (fImeOwnerIsBottom) { 03649 for (pwndT = pwndInsertAfter; pwndT; pwndT = pwndT->spwndNext) { 03650 if (ImeCheckBottomIMEWindow(pwndT)) { 03651 /* 03652 * toplevel owner of pwndT->spwndNext is BOTTOMMOST 03653 */ 03654 break; 03655 } 03656 pwndInsertAfter = pwndT; 03657 } 03658 } 03659 } 03660 #endif // LATER 03661 } 03662 03663 03664 if (!TestwndChild(pwnd)) { 03665 // if (hwnd->hwndParent == hwndDesktop) -- Chicago conditional FritzS 03666 03667 if ((GETPTI(pwnd)->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE) || 03668 (GETPTI(pwnd)->ppi->W32PF_Flags & W32PF_ALLOWFOREGROUNDACTIVATE)) { 03669 03670 return pwndInsertAfter; 03671 } 03672 } 03673 03674 /* 03675 * If there is no foreground thread or this pwnd is of the foreground 03676 * thread, then let it come to the top. 03677 */ 03678 if (gpqForeground == NULL) 03679 return pwndInsertAfter; 03680 03681 if (GETPTI(pwnd)->pq == gpqForeground) 03682 return pwndInsertAfter; 03683 03684 /* 03685 * This thread is not of the foreground queue, so search for a window 03686 * of this thread to zorder above. 03687 */ 03688 pwndT = ((pwndInsertAfter == NULL) ? 03689 pwnd->spwndParent->spwndChild : 03690 pwndInsertAfter); 03691 03692 /* 03693 * Remember the top insert after in case this first loop 03694 * fails to find a window 03695 */ 03696 pwndInsertAfterSave = pwndInsertAfter; 03697 03698 for (; pwndT != NULL; pwndT = pwndT->spwndNext) { 03699 03700 /* 03701 * This window wants to come to the top if possible. 03702 * If we're passing our own window, get out of this loop: 03703 * by now we already have pwndInsertAfter set up to the 03704 * last available window to insert after. 03705 */ 03706 if ((pwndT == pwnd) || TestWF(pwndT, WFBOTTOMMOST)) 03707 break; 03708 03709 /* 03710 * If this window isn't owned by this thread, continue. 03711 */ 03712 if (GETPTI(pwndT) != GETPTI(pwnd)) { 03713 pwndInsertAfter = pwndT; 03714 continue; 03715 } 03716 03717 /* 03718 * Don't want a window zordering below one of its top most windows 03719 * if it isn't foreground. 03720 */ 03721 if (TestWF(pwndT, WEFTOPMOST)) { 03722 pwndInsertAfter = pwndT; 03723 continue; 03724 } 03725 03726 #ifdef LATER // see #88810 03727 // FE_IME 03728 if (fImeOwnerIsBottom && ImeCheckBottomIMEWindow(pwndT)) { 03729 /* 03730 * owner of pwndT->spwndNext is BOTTOMMOST 03731 * so pwndT is the last one whose owner is not bottommost. 03732 */ 03733 pwndInsertAfter = pwndT; 03734 continue; 03735 } 03736 // end FE_IME 03737 #endif 03738 03739 /* 03740 * Ok to change zorder of top level windows because of 03741 * invisible windows laying around, but not children: 03742 * applications would go nuts if we did this. 03743 */ 03744 if (!TestwndChild(pwndT)) { 03745 if (!TestWF(pwndT, WFVISIBLE)) { 03746 pwndInsertAfter = pwndT; 03747 continue; 03748 } 03749 } 03750 03751 break; 03752 } 03753 03754 /* 03755 * If we didn't find a window in the previous loop, 03756 * it means that the thread has no 03757 * other sibling windows, so we need to put it after the 03758 * foreground window (foreground thread). Search for the 03759 * first unowned window of the foreground app to zorder 03760 * after. 03761 */ 03762 if ((pwndT == NULL) || TestWF(pwndT, WFBOTTOMMOST)) { 03763 /* 03764 * This is our first guess in case nothing works out. 03765 */ 03766 pwndInsertAfter = pwndInsertAfterSave; 03767 03768 /* 03769 * Start below the last topmost or from the top if no 03770 * topmost windows. 03771 */ 03772 if ((pwndT = pwndInsertAfter) == NULL) 03773 pwndT = pwnd->spwndParent->spwndChild; 03774 03775 /* 03776 * ptiTop is the pti of the active window in the foreground queue! 03777 */ 03778 ptiTop = NULL; 03779 if (gpqForeground->spwndActive != NULL) 03780 ptiTop = GETPTI(gpqForeground->spwndActive); 03781 03782 for (; pwndT != NULL; pwndT = pwndT->spwndNext) { 03783 03784 if (TestWF(pwndT, WFBOTTOMMOST)) 03785 break; 03786 03787 /* 03788 * If not the top most thread, continue. 03789 */ 03790 if (GETPTI(pwndT) != ptiTop) 03791 continue; 03792 03793 /* 03794 * Found one of the foreground thread. Remember this 03795 * as the next best guess. Try to find an unowned 03796 * visible window, which would indicate the main 03797 * window of the foreground thread. If owned, 03798 * continue. 03799 */ 03800 if (pwndT->spwndOwner != NULL) { 03801 pwndInsertAfter = pwndT; 03802 continue; 03803 } 03804 03805 /* 03806 * Unowned and of the foreground thread. Is it visible? 03807 * If not, get out of here. 03808 */ 03809 if (!TestWF(pwndT, WFVISIBLE)) 03810 continue; 03811 #ifdef LATER // see #88810 03812 // FE_IME 03813 if (fImeOwnerIsBottom && ImeCheckBottomIMEWindow(pwndT)) { 03814 continue; 03815 } 03816 // end FE_IME 03817 #endif 03818 03819 /* 03820 * Best possible match so far: unowned visible window 03821 * of the foreground thread. 03822 */ 03823 pwndInsertAfter = pwndT; 03824 } 03825 } 03826 03827 UserAssert(pwnd != pwndInsertAfter); 03828 03829 return pwndInsertAfter; 03830 }

__inline void cDecVis PWND  pwnd  ) 
 

Definition at line 5143 of file swp.c.

References FVisCountable(), GETPTI, and NULL.

Referenced by DecVisWindows(), and SetMinimize().

05144 { 05145 UserAssert(pwnd != NULL); 05146 05147 if (FVisCountable(pwnd)) 05148 GETPTI(pwnd)->cVisWindows--; 05149 }

int CheckTopmost PWINDOWPOS  ppos  ) 
 

Definition at line 3970 of file swp.c.

References _GetWindow(), CalcForegroundInsertAfter(), CTM_NOCHANGE, CTM_NOTOPMOST, CTM_TOPMOST, GetLastTopMostWindow(), GETPTI, GETTOPMOSTINSERTAFTER, HW, NULL, ppos, PW, TestWF, and WEFTOPMOST.

Referenced by ZOrderByOwner().

03972 { 03973 PWND pwnd, pwndInsertAfter, pwndT; 03974 03975 /* 03976 * BACKWARD COMPATIBILITY HACK 03977 * 03978 * If we're activating a window and Z-ordering too, we must ignore the 03979 * specified Z order and bring the window to the top, EXCEPT in the 03980 * following conditions: 03981 * 03982 * 1. The window is already active (in which case, the activation code 03983 * will not be bringing the window to the top) 03984 * 03985 * 2. HWND_TOP or HWND_NOTOPMOST is specified. This allows us to 03986 * activate and move to topmost or nontopmost at the same time. 03987 * 03988 * NOTE: It would have been possible to modify ActivateWindow() to 03989 * take a flag to prevent it from ever doing the BringWindowToTop, 03990 * thus allowing SetWindowPos() to properly honor pwndInsertBehind 03991 * AND activation, but this change was considered too late in the 03992 * game -- there could be problems with existing 3.1 apps, such as 03993 * PenWin, etc. 03994 */ 03995 pwnd = PW(ppos->hwnd); 03996 if (!(ppos->flags & SWP_NOACTIVATE) && 03997 !(ppos->flags & SWP_NOZORDER) && 03998 (ppos->hwndInsertAfter != HWND_TOPMOST && 03999 ppos->hwndInsertAfter != HWND_NOTOPMOST) && 04000 (pwnd != GETPTI(pwnd)->pq->spwndActive)) { 04001 ppos->hwndInsertAfter = HWND_TOP; 04002 } 04003 04004 /* 04005 * If we're not Z-ordering, don't do anything. 04006 */ 04007 if (ppos->flags & SWP_NOZORDER) 04008 return CTM_NOCHANGE; 04009 04010 04011 if (ppos->hwndInsertAfter == HWND_BOTTOM) { 04012 04013 return CTM_NOTOPMOST; 04014 04015 } else if (ppos->hwndInsertAfter == HWND_NOTOPMOST) { 04016 04017 /* 04018 * If currently topmost, move to top of non-topmost list. 04019 * Otherwise, no change. 04020 * 04021 * Note that we don't set SWP_NOZORDER -- we still need to 04022 * check the TOGGLETOPMOST bits in ChangeStates() 04023 */ 04024 if (TestWF(pwnd, WEFTOPMOST)) { 04025 04026 pwndT = GetLastTopMostWindow(); 04027 ppos->hwndInsertAfter = HW(pwndT); 04028 04029 if (ppos->hwndInsertAfter == ppos->hwnd) { 04030 pwndT = _GetWindow(pwnd, GW_HWNDPREV); 04031 ppos->hwndInsertAfter = HW(pwndT); 04032 } 04033 04034 } else { 04035 04036 pwndT = _GetWindow(pwnd, GW_HWNDPREV); 04037 ppos->hwndInsertAfter = HW(pwndT); 04038 } 04039 04040 return CTM_NOTOPMOST; 04041 04042 } else if (ppos->hwndInsertAfter == HWND_TOPMOST) { 04043 pwndT = GETTOPMOSTINSERTAFTER(pwnd); 04044 if (pwndT != NULL) { 04045 ppos->hwndInsertAfter = HW(pwndT); 04046 } else { 04047 ppos->hwndInsertAfter = HWND_TOP; 04048 } 04049 04050 return CTM_TOPMOST; 04051 04052 } else if (ppos->hwndInsertAfter == HWND_TOP) { 04053 04054 /* 04055 * If we're not topmost, position ourself after 04056 * the last topmost window. 04057 * Otherwise, make sure that no one gets in front 04058 * of a hard error box. 04059 */ 04060 if (TestWF(pwnd, WEFTOPMOST)) { 04061 pwndT = GETTOPMOSTINSERTAFTER(pwnd); 04062 if (pwndT != NULL) { 04063 ppos->hwndInsertAfter = HW(pwndT); 04064 } 04065 return CTM_NOCHANGE; 04066 } 04067 04068 /* 04069 * Calculate the window to zorder after for this window, taking 04070 * into account foreground status. 04071 */ 04072 pwndInsertAfter = CalcForegroundInsertAfter(pwnd); 04073 ppos->hwndInsertAfter = HW(pwndInsertAfter); 04074 04075 return CTM_NOCHANGE; 04076 } 04077 04078 /* 04079 * If we're being inserted after the last topmost window, 04080 * then don't change the topmost status. 04081 */ 04082 pwndT = GetLastTopMostWindow(); 04083 if (ppos->hwndInsertAfter == HW(pwndT)) 04084 return CTM_NOCHANGE; 04085 04086 /* 04087 * Otherwise, if we're inserting a TOPMOST among non-TOPMOST, 04088 * or vice versa, change the status appropriately. 04089 */ 04090 if (TestWF(PW(ppos->hwndInsertAfter), WEFTOPMOST)) { 04091 04092 if (!TestWF(pwnd, WEFTOPMOST)) { 04093 return CTM_TOPMOST; 04094 } 04095 04096 pwndT = GETTOPMOSTINSERTAFTER(pwnd); 04097 if (pwndT != NULL) { 04098 ppos->hwndInsertAfter = HW(pwndT); 04099 } 04100 04101 } else { 04102 04103 if (TestWF(pwnd, WEFTOPMOST)) 04104 return CTM_NOTOPMOST; 04105 } 04106 04107 return CTM_NOCHANGE; 04108 }

VOID ClrFTrueVis PWND  pwnd  ) 
 

Definition at line 5495 of file swp.c.

References ClrWF, DecPaintCount(), DeleteMaybeSpecialRgn(), tagWND::hrgnUpdate, NEEDSPAINT, NULL, tagWND::spwndChild, tagWND::spwndNext, TestWF, VOID(), WFINTERNALPAINT, and WFVISIBLE.

Referenced by SetVisible(), and xxxMinMaximize().

05497 { 05498 /* 05499 * Destroy pwnd and its children's update regions. 05500 * We do this here to guarantee that a hidden window 05501 * and its children don't have update regions. 05502 * 05503 * This fixes bugs when destroying windows that have 05504 * update regions (SendDestroyMessages) among others 05505 * and allows us to simplify SetParent(). This was 05506 * deemed better than hacking DoPaint() and/or 05507 * DestroyWindow(). 05508 * 05509 * We can stop recursing when we find a window that doesn't 05510 * have the visible bit set, because by definition it won't 05511 * have any update regions below it (this routine will have been called) 05512 */ 05513 if (NEEDSPAINT(pwnd)) { 05514 05515 DeleteMaybeSpecialRgn(pwnd->hrgnUpdate); 05516 05517 ClrWF(pwnd, WFINTERNALPAINT); 05518 05519 pwnd->hrgnUpdate = NULL; 05520 DecPaintCount(pwnd); 05521 } 05522 05523 for (pwnd = pwnd->spwndChild; pwnd != NULL; pwnd = pwnd->spwndNext) { 05524 05525 /* 05526 * pwnd->fs &= ~WF_TRUEVIS; 05527 */ 05528 if (TestWF(pwnd, WFVISIBLE)) 05529 ClrFTrueVis(pwnd); 05530 } 05531 }

BOOL CombineOldNewVis HRGN  hrgn,
HRGN  hrgnVisOld,
HRGN  hrgnVisNew,
UINT  crgn,
UINT  fsRgnEmpty
 

Definition at line 2467 of file swp.c.

References BOOL, CopyRgn, FALSE, RE_VISNEW, RE_VISOLD, and TRUE.

Referenced by zzzBltValidBits().

02473 { 02474 switch (fsRgnEmpty & (RE_VISOLD | RE_VISNEW)) { 02475 case RE_VISOLD: 02476 02477 /* 02478 * If we're calculating old - new and old is empty, then result is 02479 * empty. Otherwise, result is new. 02480 */ 02481 if (crgn == RGN_DIFF) 02482 return FALSE; 02483 02484 CopyRgn(hrgn, hrgnVisNew); 02485 break; 02486 02487 case RE_VISNEW: 02488 02489 /* 02490 * New is empty: result will be the old. 02491 */ 02492 CopyRgn(hrgn, hrgnVisOld); 02493 break; 02494 02495 case RE_VISNEW | RE_VISOLD: 02496 02497 /* 02498 * Both empty: so's the result. 02499 */ 02500 return FALSE; 02501 02502 case 0: 02503 02504 /* 02505 * Neither are empty: do the real combine. 02506 */ 02507 switch (GreCombineRgn(hrgn, hrgnVisOld, hrgnVisNew, crgn)) { 02508 case NULLREGION: 02509 case ERROR: 02510 return FALSE; 02511 02512 default: 02513 break; 02514 } 02515 break; 02516 } 02517 02518 return TRUE; 02519 }

VOID DecVisWindows PWND  pwnd  ) 
 

Definition at line 5156 of file swp.c.

References cDecVis(), ISTS, and VOID().

Referenced by SetMinimize(), SetVisible(), and xxxSetWindowStyle().

05158 { 05159 cDecVis(pwnd); 05160 05161 #if DBG 05162 if (!ISTS()) 05163 VerifycVisWindows(pwnd); 05164 #endif 05165 }

void DestroySMWP PSMWP  psmwp  ) 
 

Definition at line 64 of file swp.c.

References tagSMWP::acvr, tagSMWP::bHandle, BOOL, tagSMWP::ccvr, tagSMWP::ccvrAlloc, CheckCritIn, CLEAR_PUDF, CVR, DBGCheskSMWP, gSMWP, HMFreeObject(), HMMarkObjectDestroy(), tagCVR::hrgnInterMonitor, NULL, PUDF_GSMWPINUSE, TEST_PUDF, and TRUE.

Referenced by _DeferWindowPos(), and xxxEndDeferWindowPosEx().

00065 { 00066 BOOL fFree; 00067 00068 CheckCritIn(); 00069 00070 DBGCheskSMWP(psmwp); 00071 /* 00072 * First mark the object for destruction. This tells the locking code 00073 * that we want to destroy this object when the lock count goes to 0. 00074 * If this returns FALSE, we can't destroy the object yet. 00075 */ 00076 if (psmwp->bHandle) { 00077 if (!HMMarkObjectDestroy(psmwp)) { 00078 return; 00079 } 00080 fFree = TRUE; 00081 } else { 00082 /* 00083 * Is this the global cached structure? 00084 */ 00085 fFree = (psmwp != &gSMWP); 00086 } 00087 00088 if (psmwp->acvr) { 00089 00090 /* 00091 * Free any hrgnInterMonitor stuff we accumulated. 00092 */ 00093 PCVR pcvr; 00094 int ccvr; 00095 00096 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 00097 if (pcvr->hrgnInterMonitor != NULL) { 00098 GreDeleteObject(pcvr->hrgnInterMonitor); 00099 } 00100 } 00101 00102 if (fFree) { 00103 UserFreePool(psmwp->acvr); 00104 } 00105 } 00106 00107 /* 00108 * Ok to destroy... Free the handle (which will free the object 00109 * and the handle). 00110 */ 00111 if (psmwp->bHandle) { 00112 HMFreeObject(psmwp); 00113 } else if (fFree) { 00114 UserFreePool(psmwp); 00115 } else { 00116 UserAssert(TEST_PUDF(PUDF_GSMWPINUSE)); 00117 CLEAR_PUDF(PUDF_GSMWPINUSE); 00118 /* 00119 * If acvr grew too much, shrink it. 00120 * Don't use realloc since we don't care about the left over data 00121 */ 00122 if (psmwp->ccvrAlloc > 8) { 00123 PCVR pcvr = UserAllocPool(4 * sizeof(CVR), TAG_SWP); 00124 if (pcvr != NULL) { 00125 UserFreePool(psmwp->acvr); 00126 psmwp->acvr = pcvr; 00127 psmwp->ccvrAlloc = 4; 00128 } 00129 } 00130 } 00131 }

PWINDOWPOS FindValidWindowPos PSMWP  psmwp  ) 
 

Definition at line 653 of file swp.c.

References tagSMWP::acvr, tagSMWP::ccvr, NULL, and tagCVR::pos.

Referenced by xxxCalcValidRects(), xxxEndDeferWindowPosEx(), and ZOrderByOwner().

00655 { 00656 int i; 00657 00658 for (i = 0; i < psmwp->ccvr; i++) { 00659 00660 if (psmwp->acvr[i].pos.hwnd != NULL) 00661 return &psmwp->acvr[i].pos; 00662 } 00663 00664 return NULL; 00665 }

void FixBogusSWP PWND  pwnd,
int *  px,
int *  py,
int  cx,
int  cy,
UINT  flags
 

Definition at line 5919 of file swp.c.

References _MonitorFromWindow(), cy, GetPrimaryMonitor(), IntersectRect(), IsRectBogus(), tagWND::rcWindow, tagMONITOR::rcWork, and tagWND::spwndOwner.

Referenced by xxxSetWindowPos().

05920 { 05921 PMONITOR pMonitor; 05922 05923 pMonitor = _MonitorFromWindow(pwnd->spwndOwner, MONITOR_DEFAULTTONEAREST); 05924 05925 // 05926 // only check for a bogus SWP if the owner is not on the primary 05927 // 05928 if (pMonitor != GetPrimaryMonitor()) { 05929 05930 // 05931 // get the current size if SWP_NOSIZE is set 05932 // 05933 if (flags & SWP_NOSIZE) { 05934 cx = pwnd->rcWindow.right - pwnd->rcWindow.left; 05935 cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top; 05936 } 05937 05938 // 05939 // see if the app is trying to center or clip the window 05940 // 05941 if (IsRectBogus(*px, *py, cx, cy)) 05942 { 05943 RECT rc; 05944 05945 #if DBG 05946 int oldX = *px; 05947 int oldY = *py; 05948 #endif 05949 05950 // 05951 // the app wants to center/clip the window 05952 // we will have to do it for them. 05953 // 05954 // get the window rect of the parent and 05955 // intersect that with the work area of 05956 // the owning monitor, then center the 05957 // window to this rect. 05958 // 05959 IntersectRect(&rc, &pMonitor->rcWork, &pwnd->spwndOwner->rcWindow); 05960 05961 // 05962 // new multimonior friendly position. 05963 // 05964 *px = rc.left + (rc.right - rc.left - cx) / 2; 05965 *py = rc.top + (rc.bottom - rc.top - cy) / 2; 05966 05967 // 05968 // now clip to the work area. 05969 // 05970 if (*px + cx > pMonitor->rcWork.right) { 05971 *px = pMonitor->rcWork.right - cx; 05972 } 05973 05974 if (*py + cy > pMonitor->rcWork.bottom) { 05975 *py = pMonitor->rcWork.bottom - cy; 05976 } 05977 05978 if (*px < pMonitor->rcWork.left) { 05979 *px = pMonitor->rcWork.left; 05980 } 05981 05982 if (*py < pMonitor->rcWork.top) { 05983 *py = pMonitor->rcWork.top; 05984 } 05985 05986 RIPMSG0(RIP_WARNING | RIP_THERESMORE, "SetWindowPos detected that your app is centering or clipping"); 05987 RIPMSG0(RIP_WARNING | RIP_THERESMORE | RIP_NONAME, "a window to the primary monitor when its owner is on a different monitor."); 05988 RIPMSG0(RIP_WARNING | RIP_THERESMORE | RIP_NONAME, "Consider fixing your app to use the Window Manager Multimonitor APIs."); 05989 RIPMSG4(RIP_WARNING | RIP_NONAME, "SetWindowPos moved the window from (%d,%d) to (%d,%d).\n", 05990 oldX, oldY, *px, *py); 05991 } 05992 } 05993 }

BOOL FVisCountable PWND  pwnd  ) 
 

Definition at line 5107 of file swp.c.

References BOOL, FALSE, FNID_DESKTOP, FTopLevel, GETFNID, TestWF, TRUE, WFDESTROYED, and WFMINIMIZED.

Referenced by cDecVis(), HMChangeOwnerThread(), and IncVisWindows().

05108 { 05109 if (!TestWF(pwnd, WFDESTROYED)) { 05110 if ((GETFNID(pwnd) == FNID_DESKTOP) || 05111 (FTopLevel(pwnd) && !TestWF(pwnd, WFMINIMIZED))) { 05112 return TRUE; 05113 } 05114 } 05115 return FALSE; 05116 }

PWND GetLastNonBottomMostWindow PWND  pwnd,
BOOL  fSkipSelf
 

Definition at line 679 of file swp.c.

References NULL, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, TestWF, and WFBOTTOMMOST.

Referenced by CalcForegroundInsertAfter(), and ValidateZorder().

00682 { 00683 PWND pwndT; 00684 PWND pwndLast = NULL; 00685 00686 for (pwndT = pwnd->spwndParent->spwndChild; 00687 pwndT && !TestWF(pwndT, WFBOTTOMMOST); 00688 pwndT = pwndT->spwndNext) { 00689 00690 if (!fSkipSelf || (pwnd != pwndT)) 00691 pwndLast = pwndT; 00692 } 00693 00694 return pwndLast; 00695 }

PWND GetLastTopMostWindow VOID   ) 
 

Definition at line 1436 of file swp.c.

References NULL, tagDESKTOP::pDeskInfo, PtiCurrent, tagDESKTOPINFO::spwnd, tagWND::spwndChild, tagWND::spwndNext, TestWF, and WEFTOPMOST.

Referenced by _GetNextQueueWindow(), CalcForegroundInsertAfter(), CheckTopmost(), ValidateZorder(), xxxActivateOnMinimize(), and xxxCalcValidRects().

01437 { 01438 PWND pwndT; 01439 PDESKTOP pdesk = PtiCurrent()->rpdesk; 01440 01441 if (pdesk == NULL) 01442 return NULL; 01443 01444 pwndT = pdesk->pDeskInfo->spwnd->spwndChild; 01445 01446 if (!pwndT || !TestWF(pwndT, WEFTOPMOST)) 01447 return NULL; 01448 01449 while (pwndT->spwndNext) { 01450 01451 if (!TestWF(pwndT->spwndNext, WEFTOPMOST)) 01452 break; 01453 01454 pwndT = pwndT->spwndNext; 01455 } 01456 01457 return pwndT; 01458 }

PWND GetRealOwner PWND  pwnd  ) 
 

Definition at line 3430 of file swp.c.

References NULL, tagWND::spwndOwner, and tagWND::spwndParent.

Referenced by AddSelfAndOwnees(), NextOwnedWindow(), ZOrderByOwner(), and ZOrderByOwner2().

03432 { 03433 PWND pwndParent = pwnd->spwndParent; 03434 03435 /* 03436 * A frame window owned by itself is "unowned" 03437 */ 03438 if (pwnd != pwnd->spwndOwner && (pwnd = pwnd->spwndOwner) != NULL) { 03439 03440 /* 03441 * The NULL test is in case the owner is higher than the 03442 * passed in window (e.g. your owner IS your parent) 03443 */ 03444 while (pwnd != NULL && pwnd->spwndParent != pwndParent) 03445 pwnd = pwnd->spwndParent; 03446 } 03447 03448 return pwnd; 03449 }

PWND GetTopMostInsertAfter PWND  pwnd  ) 
 

Definition at line 3843 of file swp.c.

References FNID_MENU, FNID_SWITCH, GETFNID, GETPTI, gHardErrorHandler, grpdeskLogon, NULL, tagDESKTOP::pDeskInfo, tagTHREADINFO::ppi, tagWINDOWSTATION::pTerm, tagHARDERRORHANDLER::pti, PtiCurrent, tagTHREADINFO::rpdesk, tagDESKTOP::rpwinstaParent, tagDESKTOPINFO::spwnd, tagWND::spwndChild, tagWND::spwndNext, TestWF, and WEFTOPMOST.

03844 { 03845 PWND pwndT; 03846 PTHREADINFO ptiCurrent; 03847 PDESKTOP pdesk; 03848 WORD wfnid; 03849 03850 /* 03851 * If you hit this assertion, you're probably not using the 03852 * GETTOPMOSTINSERTAFTER macro to make this call. 03853 */ 03854 UserAssert(gHardErrorHandler.pti != NULL); 03855 /* 03856 * pwnd: Menu and switch (ALT-TAB) windows can go on top. 03857 */ 03858 wfnid = GETFNID(pwnd); 03859 if ((wfnid == FNID_MENU) || (wfnid == FNID_SWITCH)) { 03860 return NULL; 03861 } 03862 03863 /* 03864 * pti: If this is the error handler thread, don't bother any longer. 03865 * Screen saver can go on top too. 03866 */ 03867 ptiCurrent = PtiCurrent(); 03868 UserAssert(ptiCurrent != NULL); 03869 03870 if (ptiCurrent == gHardErrorHandler.pti || (ptiCurrent->ppi->W32PF_Flags & W32PF_SCREENSAVER)) { 03871 return NULL; 03872 } 03873 03874 /* 03875 * pdesk: Leave the logon desktop alone. 03876 * Make sure the hard error box is on this desktop 03877 */ 03878 pdesk = ptiCurrent->rpdesk; 03879 UserAssert(pdesk != NULL); 03880 UserAssert(pdesk->rpwinstaParent); 03881 UserAssert(pdesk->rpwinstaParent->pTerm); 03882 03883 if ((pdesk == grpdeskLogon) 03884 || (pdesk != gHardErrorHandler.pti->rpdesk)) { 03885 return NULL; 03886 } 03887 03888 /* 03889 * Walk the window list looking for the hard error box. 03890 * Start searching from the current desktop's first child. 03891 * Note that the harderror box migth not be created yet. 03892 */ 03893 UserAssert(pdesk->pDeskInfo); 03894 UserAssert(pdesk->pDeskInfo->spwnd); 03895 03896 for (pwndT = pdesk->pDeskInfo->spwnd->spwndChild; 03897 pwndT != NULL; pwndT = pwndT->spwndNext) { 03898 03899 /* 03900 * Hard error boxes are always top most. 03901 */ 03902 if (!TestWF(pwndT, WEFTOPMOST)) { 03903 break; 03904 } 03905 03906 /* 03907 * If this window was created by the hard error handler thread, 03908 * then this is it 03909 */ 03910 if (gHardErrorHandler.pti == GETPTI(pwndT)) { 03911 return pwndT; 03912 } 03913 } 03914 03915 return NULL; 03916 }

HWND HWInsertAfter PWND  pwnd  ) 
 

Definition at line 339 of file swp.c.

References HW.

Referenced by _DeferWindowPos(), and ValidateZorder().

00341 { 00342 /* 00343 * HWND_GROUPTOTOP and HWND_TOPMOST are the same thing. 00344 */ 00345 switch ((ULONG_PTR)pwnd) { 00346 case (ULONG_PTR)HWND_TOP: 00347 case (ULONG_PTR)HWND_BOTTOM: 00348 case (ULONG_PTR)HWND_TOPMOST: 00349 case (ULONG_PTR)HWND_NOTOPMOST: 00350 return (HWND)pwnd; 00351 00352 default: 00353 return HW(pwnd); 00354 } 00355 }

VOID IncVisWindows PWND  pwnd  ) 
 

Definition at line 5123 of file swp.c.

References FVisCountable(), GETPTI, ISTS, and VOID().

Referenced by SetMinimize(), SetVisible(), and xxxSetWindowStyle().

05125 { 05126 if (FVisCountable(pwnd)) 05127 GETPTI(pwnd)->cVisWindows++; 05128 05129 #if DBG 05130 if (!ISTS()) 05131 VerifycVisWindows(pwnd); 05132 #endif 05133 }

PSMWP InternalBeginDeferWindowPos int  cwndHint  ) 
 

Definition at line 231 of file swp.c.

References tagSMWP::acvr, AllocateCvr(), tagSMWP::ccvr, tagSMWP::ccvrAlloc, CheckCritIn, DBGCheskSMWP, gSMWP, NULL, PUDF_GSMWPINUSE, SET_PUDF, and TEST_PUDF.

Referenced by xxxArrangeIconicWindows(), xxxDesktopRecalc(), xxxMinMaximize(), xxxProcessSetWindowPosEvent(), xxxSetWindowPos(), and xxxSetWindowRgn().

00232 { 00233 PSMWP psmwp; 00234 00235 CheckCritIn(); 00236 00237 /* 00238 * If gSMWP in being used, allocate one. 00239 * Note that SMWP is zero init but CVR is not; _DeferWindowPos initializes it 00240 */ 00241 if (TEST_PUDF(PUDF_GSMWPINUSE) || (cwndHint > gSMWP.ccvrAlloc)) { 00242 psmwp = (PSMWP)UserAllocPoolWithQuotaZInit(sizeof(SMWP), TAG_SWP); 00243 if (psmwp == NULL) { 00244 return NULL; 00245 } 00246 if (!AllocateCvr(psmwp, cwndHint)) { 00247 UserFreePool(psmwp); 00248 return NULL; 00249 } 00250 } else { 00251 SET_PUDF(PUDF_GSMWPINUSE); 00252 psmwp = &gSMWP; 00253 RtlZeroMemory(&gSMWP, FIELD_OFFSET(SMWP, ccvrAlloc)); 00254 UserAssert(gSMWP.ccvr == 0); 00255 UserAssert(gSMWP.acvr != NULL); 00256 } 00257 00258 DBGCheskSMWP(psmwp); 00259 return psmwp; 00260 }

BOOL IsBehind PWND  pwnd,
PWND  pwndReference
 

Definition at line 4153 of file swp.c.

References BOOL, FALSE, NULL, tagWND::spwndNext, and TRUE.

Referenced by AddSelfAndOwnees().

04156 { 04157 04158 /* 04159 * Starting at pwnd, move down until we reach the end of the window 04160 * list, or until we reach pwndReference. If we encounter pwndReference, 04161 * then pwnd is above pwndReference, so return FALSE. If we get to the 04162 * end of the window list, pwnd is behind, so return TRUE. 04163 */ 04164 if (pwndReference == (PWND)HWND_TOP) 04165 return TRUE; 04166 04167 if (pwndReference == (PWND)HWND_BOTTOM) 04168 return FALSE; 04169 04170 for ( ; pwnd != NULL; pwnd = pwnd->spwndNext) { 04171 if (pwnd == pwndReference) 04172 return FALSE; 04173 } 04174 04175 return TRUE; 04176 }

BOOL IsMaxedRect LPRECT  lprcWithin,
PCSIZERECT  psrcMaybe
 

Definition at line 5283 of file swp.c.

References BOOL, tagSIZERECT::cx, tagSIZERECT::cy, tagSIZERECT::x, and tagSIZERECT::y.

Referenced by xxxCheckFullScreen().

05286 { 05287 return(psrcMaybe->x <= lprcWithin->left && 05288 psrcMaybe->y <= lprcWithin->top && 05289 psrcMaybe->cx >= lprcWithin->right - lprcWithin->left && 05290 psrcMaybe->cy >= lprcWithin->bottom - lprcWithin->top); 05291 }

BOOL IsOwnee PWND  pwndOwnee,
PWND  pwndOwner
 

Definition at line 4120 of file swp.c.

References BOOL, FALSE, NULL, tagWND::spwndParent, and TRUE.

Referenced by ZOrderByOwner2().

04123 { 04124 PWND pwnd; 04125 04126 while (pwndOwnee != NULL) { 04127 04128 /* 04129 * See if pwndOwnee is a child of pwndOwner... 04130 */ 04131 for (pwnd = pwndOwnee; pwnd != NULL; pwnd = pwnd->spwndParent) { 04132 if (pwnd == pwndOwner) 04133 return TRUE; 04134 } 04135 04136 /* 04137 * If the window doesn't own itself, then set the owner 04138 * to itself. 04139 */ 04140 pwndOwnee = (pwndOwnee->spwndOwner != pwndOwnee ? 04141 pwndOwnee->spwndOwner : NULL); 04142 } 04143 04144 return FALSE; 04145 }

BOOL IsRectBogus int  x,
int  y,
int  cx,
int  cy
 

Definition at line 5895 of file swp.c.

References cy, GetPrimaryMonitor(), tagMONITOR::rcMonitor, tagMONITOR::rcWork, and TestRectBogus().

Referenced by FixBogusSWP().

05896 { 05897 PMONITOR pMonitorPrimary = GetPrimaryMonitor(); 05898 05899 return TestRectBogus(&pMonitorPrimary->rcWork, x, y, cx, cy) || 05900 TestRectBogus(&pMonitorPrimary->rcMonitor, x, y, cx, cy); 05901 }

BOOL IsStillWindowC HWND  hwndc  ) 
 

Definition at line 562 of file swp.c.

References BOOL, RevalidateHwnd, and TRUE.

Referenced by BltValidInit(), ValidateSmwp(), xxxCalcValidRects(), xxxSendChangedMsgs(), zzzBltValidBits(), and zzzChangeStates().

00564 { 00565 switch ((ULONG_PTR)hwndc) { 00566 case (ULONG_PTR)HWND_TOP: 00567 case (ULONG_PTR)HWND_BOTTOM: 00568 case (ULONG_PTR)HWND_TOPMOST: 00569 case (ULONG_PTR)HWND_NOTOPMOST: 00570 return TRUE; 00571 00572 default: 00573 /* 00574 * Make sure we're going to insert after a window that's 00575 * (1) Valid 00576 * (2) Peer 00577 */ 00578 return (RevalidateHwnd(hwndc) != 0); 00579 } 00580 }

PWND NextOwnedWindow PWND  pwnd,
PWND  pwndOwner,
PWND  pwndParent
 

Definition at line 3460 of file swp.c.

References GetRealOwner(), NULL, tagWND::spwndChild, and tagWND::spwndNext.

Referenced by AddSelfAndOwnees(), SetTopmost(), ZOrderByOwner(), and ZOrderByOwner2().

03464 { 03465 if (pwnd == NULL) { 03466 pwnd = pwndParent->spwndChild; 03467 goto loop; 03468 } 03469 03470 while ((pwnd = pwnd->spwndNext) != NULL) { 03471 03472 loop: 03473 03474 /* 03475 * If owner of pwnd is pwndOwner, break out of here... 03476 */ 03477 if (pwndOwner == GetRealOwner(pwnd)) 03478 break; 03479 } 03480 03481 return pwnd; 03482 }

VOID OffsetChildren PWND  pwnd,
int  dx,
int  dy,
LPRECT  prcHitTest
 

Definition at line 5543 of file swp.c.

References FindSpb(), gpDispInfo, tagDISPLAYINFO::hDev, HRGN_FULL, IntersectRect(), NULL, OffsetRect(), PtoHq, tagWND::rcWindow, tagWND::spwndChild, TestWF, VOID(), WEFLAYERED, WFHASSPB, and WFMAXFAKEREGIONAL.

Referenced by xxxScrollWindowEx(), and zzzChangeStates().

05548 { 05549 RECT rc; 05550 PWND pwndStop; 05551 05552 if (!pwnd->spwndChild) 05553 return; 05554 05555 pwndStop = pwnd; 05556 pwnd = pwndStop->spwndChild; 05557 for (;;) { 05558 /* 05559 * Skip windows that don't intersect prcHitTest... 05560 */ 05561 if (prcHitTest && !IntersectRect(&rc, prcHitTest, &pwnd->rcWindow)) 05562 goto NextWindow; 05563 05564 pwnd->rcWindow.left += dx; 05565 pwnd->rcWindow.right += dx; 05566 pwnd->rcWindow.top += dy; 05567 pwnd->rcWindow.bottom += dy; 05568 05569 pwnd->rcClient.left += dx; 05570 pwnd->rcClient.right += dx; 05571 pwnd->rcClient.top += dy; 05572 pwnd->rcClient.bottom += dy; 05573 05574 if (pwnd->hrgnUpdate > HRGN_FULL && !TestWF(pwnd, WFMAXFAKEREGIONAL)) { 05575 GreOffsetRgn(pwnd->hrgnUpdate, dx, dy); 05576 } 05577 05578 /* 05579 * Change position of window region, if it has one 05580 */ 05581 if (pwnd->hrgnClip != NULL) 05582 GreOffsetRgn(pwnd->hrgnClip, dx, dy); 05583 05584 if (TestWF(pwnd, WFHASSPB)) 05585 OffsetRect(&(FindSpb(pwnd))->rc, dx, dy); 05586 05587 #ifdef CHILD_LAYERING 05588 if (TestWF(pwnd, WEFLAYERED)) { 05589 POINT ptPos = {pwnd->rcWindow.left, pwnd->rcWindow.top}; 05590 05591 GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, NULL, 05592 &ptPos, NULL, NULL, NULL, 0, NULL, 0, NULL); 05593 } 05594 #endif // CHILD_LAYERING 05595 05596 /* 05597 * Recurse into the child tree if there are children. 05598 */ 05599 if (pwnd->spwndChild) { 05600 pwnd = pwnd->spwndChild; 05601 continue; 05602 } 05603 05604 NextWindow: 05605 if (pwnd->spwndNext) { 05606 /* 05607 * Recurse to the next sibling in the list. 05608 */ 05609 pwnd = pwnd->spwndNext; 05610 } else { 05611 for (;;) { 05612 /* 05613 * We're at the end of the sibling window list. 05614 * Go to the parent's next window. 05615 */ 05616 pwnd = pwnd->spwndParent; 05617 if (pwnd == pwndStop) 05618 return; 05619 05620 if (pwnd->spwndNext) { 05621 pwnd = pwnd->spwndNext; 05622 break; 05623 } 05624 } 05625 } 05626 } 05627 }

void PreventInterMonitorBlts PCVR  pcvr  ) 
 

Definition at line 6013 of file swp.c.

References CopyOffsetRect(), CreateEmptyRgn(), tagMONITOR::dwMONFlags, tagCVR::dxBlt, tagCVR::dyBlt, EqualRect, ghrgnGDC, ghrgnInv2, gpDispInfo, tagCVR::hrgnInterMonitor, IntersectRect(), IsRectEmpty(), MONF_VISIBLE, NULL, tagDISPLAYINFO::pMonitorFirst, tagMONITOR::pMonitorNext, tagCVR::rcBlt, tagMONITOR::rcMonitor, SubtractRgn, and UnionRgn.

Referenced by BltValidInit().

06014 { 06015 RECT rcSrc; 06016 RECT rcDst; 06017 RECT rcSrcT; 06018 RECT rcDstT; 06019 PMONITOR pMonitor; 06020 // 06021 // If the destination is empty do nothing. 06022 // 06023 if (IsRectEmpty(&pcvr->rcBlt)) 06024 return; 06025 06026 // 06027 // Get the source rect (rcBlt is the destination, dxBlt/dyBlt are the 06028 // distance moved from the source). 06029 // 06030 CopyOffsetRect(&rcSrc, &pcvr->rcBlt, -pcvr->dxBlt, -pcvr->dyBlt); 06031 06032 // 06033 // Split up the source into its monitor pieces. If the source intersects 06034 // a monitor, then figure out where that part will be in the destination. 06035 // Intersect the destination part with the same monitor. The result is 06036 // the amount we can blt from the source to the dest on that monitor. 06037 // 06038 // We do this for each monitor to find the biggest blt rect. We want 06039 // the biggest because we want to repaint as little as possible. We do 06040 // bail out if both the source and dest are fully contained on the same 06041 // monitor. 06042 // 06043 for (pMonitor = gpDispInfo->pMonitorFirst; 06044 pMonitor != NULL; 06045 pMonitor = pMonitor->pMonitorNext) { 06046 06047 // 06048 // We're only interested in visible monitors 06049 // 06050 if (!(pMonitor->dwMONFlags & MONF_VISIBLE)) 06051 continue; 06052 // 06053 // If this monitor doesn't contain a piece of the source, we don't 06054 // care about it. We won't be doing a same monitor blt on it for sure. 06055 // 06056 if (!IntersectRect(&rcSrcT, &rcSrc, &pMonitor->rcMonitor)) 06057 continue; 06058 06059 // 06060 // See where this rect would be in the destination. 06061 // 06062 CopyOffsetRect(&rcDst, &rcSrcT, pcvr->dxBlt, pcvr->dyBlt); 06063 06064 // 06065 // Intersect this rect with the same monitor rect to see what piece 06066 // can be safely blted on the same monitor. 06067 // 06068 IntersectRect(&rcDstT, &rcDst, &pMonitor->rcMonitor); 06069 06070 // 06071 // Is this piece of the source staying on this monitor? 06072 // 06073 if (EqualRect(&rcDstT, &rcDst)) { 06074 // 06075 // This source piece is staying completely on this monitor when 06076 // it becomes the destination. Hence there is nothing to add 06077 // to our invalid sum, hrgnInterMonitor. 06078 // 06079 if (EqualRect(&rcSrcT, &rcSrc)) { 06080 // 06081 // The source is completely ON one monitor and moving to 06082 // a location also completely ON this monitor. Great, no 06083 // intermonitor blts whatsoever. We are done. 06084 // 06085 UserAssert(pcvr->hrgnInterMonitor == NULL); 06086 return; 06087 } else { 06088 continue; 06089 } 06090 } 06091 06092 // 06093 // OK, some piece of the source is moving across monitors. Figure 06094 // out what it is and where that piece is in the destination. That 06095 // piece in the destination must be invalidated and not blted. 06096 // 06097 if (pcvr->hrgnInterMonitor == NULL) { 06098 pcvr->hrgnInterMonitor = CreateEmptyRgn(); 06099 } 06100 06101 // 06102 // The difference between the transposed source to the dest, and the 06103 // real part of the dest that lies on this monitor, is the amount 06104 // of the source that will move across a monitor boundary. Add this 06105 // to our accumulated invalid region. 06106 // 06107 // rcDst is the whole source chunk, rcDstT is the part on the same 06108 // monitor as the source chunk. 06109 // 06110 GreSetRectRgn(ghrgnInv2, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom); 06111 GreSetRectRgn(ghrgnGDC, rcDstT.left, rcDstT.top, rcDstT.right, rcDstT.bottom); 06112 SubtractRgn(ghrgnInv2, ghrgnInv2, ghrgnGDC); 06113 UnionRgn(pcvr->hrgnInterMonitor, pcvr->hrgnInterMonitor, ghrgnInv2); 06114 } 06115 #if DBG 06116 VerifyVisibleMonitorCount(); 06117 #endif 06118 }

PWND PWInsertAfter HWND  hwnd  ) 
 

Definition at line 301 of file swp.c.

References _IsDescendant(), NULL, RevalidateHwnd, tagWND::spwndParent, TestWF, and WFDESTROYED.

Referenced by ValidateZorder(), ZOrderByOwner2(), and zzzChangeStates().

00303 { 00304 PWND pwnd; 00305 00306 /* 00307 * HWND_GROUPTOTOP and HWND_TOPMOST are the same thing. 00308 */ 00309 switch ((ULONG_PTR)hwnd) { 00310 case (ULONG_PTR)HWND_TOP: 00311 case (ULONG_PTR)HWND_BOTTOM: 00312 case (ULONG_PTR)HWND_TOPMOST: 00313 case (ULONG_PTR)HWND_NOTOPMOST: 00314 return (PWND)hwnd; 00315 00316 default: 00317 00318 /* 00319 * Don't insert after a destroyed window! It will cause the 00320 * window being z-ordered to become unlinked from it's siblings. 00321 */ 00322 if (pwnd = RevalidateHwnd(hwnd)) { 00323 00324 /* 00325 * Do not insert after a destroyed window. Put it at the 00326 * bottom of the list, if it is z-ordered at all. 00327 */ 00328 if (TestWF(pwnd, WFDESTROYED) || pwnd->spwndParent == NULL) 00329 return NULL; 00330 00331 UserAssert(_IsDescendant(pwnd->spwndParent, pwnd)); 00332 return pwnd; 00333 } 00334 00335 return NULL; 00336 } 00337 }

void SelectWindowRgn PWND  pwnd,
HRGN  hrgnClip
 

Definition at line 5753 of file swp.c.

References _MonitorFromWindow(), ClrWF, HRGN_FULL, HRGN_MONITOR, tagWND::hrgnClip, tagMONITOR::hrgnMonitor, NULL, PWNDDESKTOP, tagWND::rcWindow, SetWF, tagWND::spwndParent, TestWF, WFMAXFAKEREGIONAL, WFMAXIMIZED, and WFREALLYMAXIMIZABLE.

Referenced by xxxCreateDisconnectDesktop(), and zzzChangeStates().

05756 { 05757 /* 05758 * If there is a region already there, delete it because 05759 * a new one is being set. For maximized windows in multiple monitor 05760 * mode, we always use the monitor HRGN. We don't make a copy. This 05761 * way, when the hrgn changes because of monitor config, the window's 05762 * monitor region automatically gets updated. Clever huh? Also saves 05763 * memory. 05764 */ 05765 if (pwnd->hrgnClip != NULL) { 05766 if (TestWF(pwnd, WFMAXFAKEREGIONAL)) { 05767 ClrWF(pwnd, WFMAXFAKEREGIONAL); 05768 } else { 05769 /* 05770 * Do NOT select in a monitor region if the window is normally 05771 * regional. The MinMaximize code will always pass HRGN_MONITOR 05772 * to us no matter what. But when we get here, bail out and 05773 * don't destroy the app's region if it has one. 05774 */ 05775 if (hrgnClip == HRGN_MONITOR) 05776 return; 05777 05778 GreDeleteObject(pwnd->hrgnClip); 05779 } 05780 05781 pwnd->hrgnClip = NULL; 05782 } 05783 05784 /* 05785 * NULL or HRGN_FULL means "set to NULL". If we have a real region, 05786 * use it. USER needs to own it, and it needs to be in screen 05787 * coordinates. 05788 */ 05789 if (hrgnClip > HRGN_FULL) { 05790 05791 if (hrgnClip == HRGN_MONITOR) { 05792 PMONITOR pMonitor; 05793 05794 /* 05795 * Use the monitor region if the window is really maxed 05796 * on a monitor. It's already happened by the time we get here, 05797 * if so. And xxxCheckFullScreen will clear the reallymaximed 05798 * style for a maximized window if it doesn't cover the whole 05799 * max area. 05800 */ 05801 UserAssert(pwnd->spwndParent == PWNDDESKTOP(pwnd)); 05802 05803 if (!TestWF(pwnd, WFMAXIMIZED) || !TestWF(pwnd, WFREALLYMAXIMIZABLE)) 05804 return; 05805 05806 /* 05807 * Do nothing for windows off screen. 05808 */ 05809 pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTONULL); 05810 if (!pMonitor) 05811 return; 05812 05813 hrgnClip = pMonitor->hrgnMonitor; 05814 SetWF(pwnd, WFMAXFAKEREGIONAL); 05815 } else { 05816 if (pwnd != PWNDDESKTOP(pwnd)) { 05817 GreOffsetRgn(hrgnClip, pwnd->rcWindow.left, pwnd->rcWindow.top); 05818 } 05819 05820 GreSetRegionOwner(hrgnClip, OBJECT_OWNER_PUBLIC); 05821 } 05822 05823 pwnd->hrgnClip = hrgnClip; 05824 } 05825 }

VOID SetMinimize PWND  pwnd,
UINT  uFlags
 

Definition at line 5176 of file swp.c.

References cDecVis(), ClrWF, DecVisWindows(), IncVisWindows(), SetWF, SMIN_SET, TestWF, VOID(), WFMINIMIZED, and WFVISIBLE.

Referenced by xxxCreateWindowEx(), xxxMinMaximize(), and xxxMS_TrackMove().

05179 { 05180 /* 05181 * Note that Dec and IncVisWindows check the WFMINIMIZED flag, so the order 05182 * in which we set/clear the flag and call these functions is important 05183 * If the window is not WFVISIBLE, cVisWindows must not change. 05184 */ 05185 if (uFlags & SMIN_SET) { 05186 UserAssert(!TestWF(pwnd, WFMINIMIZED)); 05187 if (TestWF(pwnd, WFVISIBLE)) { 05188 /* 05189 * Decrement the count because the window is not minimized 05190 * and visible, and we're about to mark it as minimized 05191 */ 05192 05193 #if DBG 05194 cDecVis(pwnd); 05195 #else 05196 DecVisWindows(pwnd); 05197 #endif 05198 } 05199 SetWF(pwnd, WFMINIMIZED); 05200 05201 #if DBG 05202 VerifycVisWindows(pwnd); 05203 #endif 05204 } else { 05205 05206 UserAssert(TestWF(pwnd, WFMINIMIZED)); 05207 ClrWF(pwnd, WFMINIMIZED); 05208 if (TestWF(pwnd, WFVISIBLE)) { 05209 /* 05210 * Increment the count because the window is visible 05211 * and it's no longer marked as minimized 05212 */ 05213 IncVisWindows(pwnd); 05214 } 05215 } 05216 }

VOID SetTopmost PWND  pwndRoot,
BOOL  fTopmost
 

Definition at line 3498 of file swp.c.

References ClrWF, FALSE, NextOwnedWindow(), NULL, SetWF, tagWND::spwndParent, TestWF, TRUE, VOID(), WEFTOPMOST, and WFTOGGLETOPMOST.

Referenced by ZOrderByOwner().

03501 { 03502 PWND pwnd; 03503 03504 /* 03505 * If the new state is different than the current state, 03506 * then set the TOGGLETOPMOST bit, so it'll get toggled 03507 * in ChangeStates(). 03508 */ 03509 UserAssert((fTopmost == TRUE) || (fTopmost == FALSE)); 03510 if (!!TestWF(pwndRoot, WEFTOPMOST) ^ fTopmost) { 03511 SetWF(pwndRoot, WFTOGGLETOPMOST); 03512 } else { 03513 ClrWF(pwndRoot, WFTOGGLETOPMOST); 03514 } 03515 03516 pwnd = NULL; 03517 while (pwnd = NextOwnedWindow(pwnd, pwndRoot, pwndRoot->spwndParent)) { 03518 SetTopmost(pwnd, fTopmost); 03519 } 03520 03521 }

VOID SetVisible PWND  pwnd,
UINT  flags
 

Definition at line 5237 of file swp.c.

References ClrFTrueVis(), ClrWF, DecVisWindows(), IncVisWindows(), SetWF, SV_CLRFTRUEVIS, SV_SET, TestWF, VOID(), WFDESTROYED, WFINDESTROY, and WFVISIBLE.

Referenced by xxxCreateWindowEx(), xxxCreateWindowStation(), xxxDesktopThread(), xxxDestroyWindow(), xxxDWP_SetRedraw(), xxxDWPPrint(), xxxFW_DestroyAllChildren(), xxxMinimizeHungWindow(), xxxMNCloseHierarchy(), xxxProcessHungThreadEvent(), xxxShowOwnedWindows(), xxxShowWindow(), zzzActiveCursorTracking(), and zzzChangeStates().

05240 { 05241 if (flags & SV_SET) { 05242 05243 #if DBG 05244 if (TestWF(pwnd, WFINDESTROY)) { 05245 RIPMSG1(RIP_WARNING, "SetVisible: show INDESTROY %#p", pwnd); 05246 } 05247 #endif 05248 05249 if (TestWF(pwnd, WFVISIBLE)) { 05250 RIPMSG1(RIP_WARNING, "SetVisible: already visible %#p", pwnd); 05251 } else { 05252 SetWF(pwnd, WFVISIBLE); 05253 IncVisWindows(pwnd); 05254 } 05255 } else { 05256 05257 if (flags & SV_CLRFTRUEVIS) 05258 ClrFTrueVis(pwnd); 05259 05260 #if DBG 05261 if (TestWF(pwnd, WFDESTROYED)) { 05262 RIPMSG1(RIP_WARNING, "SetVisible: hide DESTROYED %#p", pwnd); 05263 } 05264 #endif 05265 05266 if (TestWF(pwnd, WFVISIBLE)) { 05267 ClrWF(pwnd, WFVISIBLE); 05268 DecVisWindows(pwnd); 05269 } else { 05270 RIPMSG1(RIP_WARNING, "SetVisible: already hidden %#p", pwnd); 05271 } 05272 } 05273 }

BOOL SwpCalcVisRgn PWND  pwnd,
HRGN  hrgn
 

Definition at line 2434 of file swp.c.

References BOOL, CalcVisRgn(), FALSE, TestWF, WFCLIPSIBLINGS, and WFVISIBLE.

Referenced by BltValidInit(), and zzzBltValidBits().

02437 { 02438 /* 02439 * If this window is invisible, then 02440 * the visrgn will be empty, so return FALSE. 02441 */ 02442 if (!TestWF(pwnd, WFVISIBLE)) 02443 return FALSE; 02444 02445 /* 02446 * Otherwise do it the hard way... 02447 */ 02448 return CalcVisRgn(&hrgn, 02449 pwnd, 02450 pwnd, 02451 (TestWF(pwnd, WFCLIPSIBLINGS) ? 02452 (DCX_CLIPSIBLINGS | DCX_WINDOW) : (DCX_WINDOW))); 02453 }

BOOL TestRectBogus RECT *  prc,
int  x,
int  y,
int  cx,
int  cy
 

Definition at line 5842 of file swp.c.

References abs, cy, FALSE, SLOP_X, SLOP_Y, and TRUE.

Referenced by IsRectBogus().

05843 { 05844 // 05845 // check for a fullscreen (or offscreen) window 05846 // 05847 if ( x <= prc->left && 05848 y <= prc->top && 05849 cx >= (prc->right - prc->left) && 05850 cy >= (prc->bottom - prc->top)) { 05851 05852 // rect is fullscreen 05853 return FALSE; 05854 } 05855 05856 // 05857 // check for the window being centered to the work area 05858 // use <= for y to catch dialogs centered "high" 05859 // (like the network logon dialog) 05860 // 05861 if ( abs(x - (prc->right + prc->left - cx) / 2) <= SLOP_X && 05862 abs(y - (prc->bottom + prc->top - cy) / 2) <= SLOP_Y ) { 05863 05864 // rect centered 05865 return TRUE; 05866 } 05867 05868 // 05869 // check for the window being cliped to the work area 05870 // 05871 if ( x == prc->left || 05872 y == prc->top || 05873 x == (prc->right - cx) || 05874 y == (prc->bottom - cy)) { 05875 05876 // rect is clipped 05877 return TRUE; 05878 } 05879 05880 return FALSE; 05881 }

BOOL TrackBackground WINDOWPOS *  ppos,
PWND  pwndPrev,
PWND  pwnd
 

Definition at line 4503 of file swp.c.

References BOOL, CalcForegroundInsertAfter(), FALSE, FSwpTopmost(), GETPTI, gptiForeground, HW, NULL, tagTHREADINFO::ppi, ppos, TestWF, TIF_16BIT, TRUE, and WEFTOPMOST.

Referenced by TrackZorder().

04504 { 04505 PWND pwndT; 04506 04507 if (pwndPrev == NULL) 04508 return FALSE; 04509 04510 /* 04511 * Is this window foreground? If so, let it go. For wow apps, 04512 * check to see if any thread of the process is foreground. 04513 */ 04514 if (GETPTI(pwnd)->TIF_flags & TIF_16BIT) { 04515 04516 if (gptiForeground == NULL) 04517 return FALSE; 04518 04519 if (GETPTI(pwnd)->ppi == gptiForeground->ppi) 04520 return FALSE; 04521 04522 } else { 04523 04524 if (GETPTI(pwnd) == gptiForeground) 04525 return FALSE; 04526 } 04527 04528 /* 04529 * Make sure the previous window is either staying or becoming 04530 * topmost. If not, continue: no top most boundary. 04531 */ 04532 if (!FSwpTopmost(pwndPrev)) 04533 return FALSE; 04534 04535 /* 04536 * Is the current window already top-most? If so then don't 04537 * calculate a special insert after. If we don't check for 04538 * this, then pwnd's insert after may be calculated as what 04539 * pwnd already is, if pwnd is the last top most window. That 04540 * would cause window links to get corrupted. 04541 */ 04542 if (TestWF(pwnd, WEFTOPMOST)) 04543 return FALSE; 04544 04545 /* 04546 * Doing this assign prevents this routine from being called 04547 * twice, since HW() is a conditional macro. 04548 */ 04549 pwndT = CalcForegroundInsertAfter(pwnd); 04550 ppos->hwndInsertAfter = HW(pwndT); 04551 return TRUE; 04552 }

PWND TrackZorder WINDOWPOS *  ppos,
PWND  pwndPrev,
HWND *  phwndTop,
HWND *  phwndReg
 

Definition at line 4583 of file swp.c.

References FSwpTopmost(), NULL, ppos, PW, TrackBackground(), and TrackZorderHelper().

Referenced by ZOrderByOwner().

04584 { 04585 PWND pwnd = PW(ppos->hwnd); 04586 04587 if (pwnd == NULL) 04588 return NULL; 04589 04590 if (TrackBackground(ppos, pwndPrev, pwnd)) { 04591 *phwndReg = ppos->hwnd; 04592 } else if (FSwpTopmost(pwnd)) { 04593 TrackZorderHelper(ppos, phwndTop); 04594 } else { 04595 TrackZorderHelper(ppos, phwndReg); 04596 } 04597 04598 return pwnd; 04599 }

void TrackZorderHelper WINDOWPOS *  ppos,
HWND *  phwnd
 

Definition at line 4563 of file swp.c.

References NULL, and ppos.

Referenced by TrackZorder().

04564 { 04565 /* 04566 * phwnd (hwndTopmost or hwndRegular) have been initialized to NULL before 04567 * the beginning of the scan. This way the first hwndInsertAfter that 04568 * we process remains with the value that was previously calculated. 04569 */ 04570 if (*phwnd != NULL) { 04571 04572 #if DBG 04573 if (ppos->hwndInsertAfter != *phwnd) { 04574 RIPMSG0(RIP_WARNING, "TrackZorder: modified hwndInsertAfter"); 04575 } 04576 #endif 04577 04578 ppos->hwndInsertAfter = *phwnd; 04579 } 04580 *phwnd = ppos->hwnd; 04581 }

BOOL ValidateSmwp PSMWP  psmwp,
BOOL *  pfSyncPaint
 

Definition at line 591 of file swp.c.

References tagSMWP::acvr, BOOL, tagSMWP::ccvr, FALSE, IsStillWindowC(), NULL, tagCVR::pos, PW, RevalidateHwnd, tagWND::spwndParent, TRUE, and ValidateWindowPos().

Referenced by xxxEndDeferWindowPosEx().

00594 { 00595 PCVR pcvr; 00596 PWND pwndParent; 00597 PWND pwndT; 00598 int ccvr; 00599 00600 *pfSyncPaint = TRUE; 00601 00602 pwndT = RevalidateHwnd(psmwp->acvr[0].pos.hwnd); 00603 00604 if (pwndT == NULL) 00605 return FALSE; 00606 00607 pwndParent = pwndT->spwndParent; 00608 00609 /* 00610 * Validate the passed-in WINDOWPOS structs, and find a window to activate. 00611 */ 00612 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 00613 00614 if (!ValidateWindowPos(pcvr, NULL)) { 00615 pcvr->pos.hwnd = NULL; 00616 continue; 00617 } 00618 00619 /* 00620 * All windows in the pos list must have the same parent. 00621 * If not, yell and return FALSE. 00622 */ 00623 UserAssert(IsStillWindowC(pcvr->pos.hwnd)); 00624 00625 UserAssert(PW(pcvr->pos.hwnd)); 00626 if (PW(pcvr->pos.hwnd)->spwndParent != pwndParent) { 00627 RIPERR0(ERROR_HWNDS_HAVE_DIFF_PARENT, RIP_VERBOSE, ""); 00628 return FALSE; 00629 } 00630 00631 /* 00632 * If SWP_DEFERDRAWING is set for any of the windows, suppress 00633 * DoSyncPaint() call later. 00634 */ 00635 if (pcvr->pos.flags & SWP_DEFERDRAWING) 00636 *pfSyncPaint = FALSE; 00637 } 00638 00639 return TRUE; 00640 }

BOOL ValidateWindowPos PCVR  pcvr,
PWND  pwndParent
 

Definition at line 429 of file swp.c.

References BOOL, FALSE, FSwpTopmost(), GETPTI, NULL, tagCVR::pos, tagCVR::pti, PWNDDESKTOP, RevalidateHwnd, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, TestWF, TRUE, and WFDESTROYED.

Referenced by ValidateSmwp(), and zzzChangeStates().

00430 { 00431 PWND pwnd; 00432 PWND pwndInsertAfter; 00433 HWND hwndInsertAfter; 00434 00435 if ((pwnd = RevalidateHwnd(pcvr->pos.hwnd)) == NULL) 00436 return FALSE; 00437 00438 /* 00439 * Save the pti 00440 */ 00441 pcvr->pti = GETPTI(pwnd); 00442 00443 00444 /* 00445 * If the SWP_NOZORDER bit is not set, validate the Insert behind window. 00446 */ 00447 if (!(pcvr->pos.flags & SWP_NOZORDER)) { 00448 BOOL fTopLevel = (pwnd->spwndParent == PWNDDESKTOP(pwnd)); 00449 /* 00450 * Do not z-order destroyed windows 00451 */ 00452 if (TestWF(pwnd, WFDESTROYED)) 00453 return FALSE; 00454 00455 hwndInsertAfter = pcvr->pos.hwndInsertAfter; 00456 /* 00457 * If pwndParent is provided, we're about to link this window so we 00458 * need to validate LinkWindow assumptions. 00459 * We have to do this since we callback after determining hwndInsertAfter. 00460 */ 00461 00462 if ((hwndInsertAfter == HWND_TOPMOST) || 00463 (hwndInsertAfter == HWND_NOTOPMOST)) { 00464 00465 if (!fTopLevel) { 00466 return FALSE; 00467 } 00468 } else if (hwndInsertAfter == HWND_TOP) { 00469 /* 00470 * if pwnd is not topmost, the first child must not be topmost. 00471 */ 00472 if ((pwndParent != NULL) && fTopLevel 00473 && !FSwpTopmost(pwnd) 00474 && (pwndParent->spwndChild != NULL) 00475 && FSwpTopmost(pwndParent->spwndChild)) { 00476 00477 RIPMSG2(RIP_WARNING, "ValidateWindowPos: pwnd is not SWPTopMost." 00478 " pwnd:%#p. hwndInsertAfter:%#p", 00479 pwnd, hwndInsertAfter); 00480 return FALSE; 00481 } 00482 } else if (hwndInsertAfter != HWND_BOTTOM) { 00483 00484 /* 00485 * Ensure pwndInsertAfter is valid 00486 */ 00487 if (((pwndInsertAfter = RevalidateHwnd(hwndInsertAfter)) == NULL) || 00488 TestWF(pwndInsertAfter, WFDESTROYED)) { 00489 00490 RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid hwndInsertAfter (%#p)", hwndInsertAfter); 00491 00492 return FALSE; 00493 } 00494 00495 /* 00496 * Ensure that pwndInsertAfter is a sibling of pwnd 00497 */ 00498 if (pwnd == pwndInsertAfter || 00499 pwnd->spwndParent != pwndInsertAfter->spwndParent) { 00500 RIPMSG2(RIP_WARNING, "hwndInsertAfter (%#p) is not a sibling " 00501 "of hwnd (%#p)", hwndInsertAfter, pcvr->pos.hwnd); 00502 return FALSE; 00503 } 00504 /* 00505 * Ensure proper topmost/nontopmost insert position 00506 */ 00507 if ((pwndParent != NULL) && fTopLevel) { 00508 if (FSwpTopmost(pwnd)) { 00509 /* 00510 * Check if we're trying to insert a topmost window after a non-topmost one. 00511 */ 00512 if (!FSwpTopmost(pwndInsertAfter)) { 00513 RIPMSG2(RIP_WARNING, "ValidateWindowPos: pwndInsertAfter is not SWPTopMost." 00514 " pwnd:%#p. pwndInsertAfter:%#p", 00515 pwnd, pwndInsertAfter); 00516 return FALSE; 00517 } 00518 } else { 00519 /* 00520 * Check if we're trying to insert a non-top most window between two 00521 * top-most ones. 00522 */ 00523 if ((pwndInsertAfter->spwndNext != NULL) 00524 && FSwpTopmost(pwndInsertAfter->spwndNext)) { 00525 00526 RIPMSG2(RIP_WARNING, "ValidateWindowPos: pwndInsertAfter->spwndNext is SWPTopMost." 00527 " pwnd:%#p. pwndInsertAfter:%#p", 00528 pwnd, pwndInsertAfter); 00529 return FALSE; 00530 } 00531 } 00532 00533 } 00534 00535 } /* if (hwndInsertAfter != HWND_TOP && hwndInsertAfter != HWND_BOTTOM) */ 00536 00537 /* 00538 * Check that the parent hasn't changed. 00539 */ 00540 if (pwndParent != NULL) { 00541 if (pwndParent != pwnd->spwndParent) { 00542 RIPMSG3(RIP_WARNING, "ValidateWindowPos: parent has changed." 00543 " pwnd:%#p. Old Parent:%#p. Current Parent:%#p", 00544 pwnd, pwndParent, pwnd->spwndParent); 00545 return FALSE; 00546 } 00547 } 00548 00549 } /* if (!(pcvr->pos.flags & SWP_NOZORDER)) */ 00550 00551 return TRUE; 00552 }

BOOL ValidateZorder PCVR  pcvr  ) 
 

Definition at line 708 of file swp.c.

References BOOL, BYTE, FALSE, GetLastNonBottomMostWindow(), GetLastTopMostWindow(), HANDLEF_DESTROY, HMPheFromObject, HW, HWInsertAfter(), LOBYTE, NULL, tagCVR::pos, PWCat, PWInsertAfter(), PWND_BOTTOM, PWND_TOP, RevalidateCatHwnd, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, TestWF, TRUE, WEFTOPMOST, WFBOTTOMMOST, WFDESTROYED, and WFTOGGLETOPMOST.

Referenced by xxxCalcValidRects(), and zzzChangeStates().

00710 { 00711 PWND pwnd; 00712 PWND pwndPrev; 00713 PWND pwndInsertAfter; 00714 BYTE bTopmost; 00715 00716 /* 00717 * Validate just to make sure this routine doesn't do anything bogus. 00718 * Its caller will actually redetect and handle the error. 00719 */ 00720 UserAssert(RevalidateCatHwnd(pcvr->pos.hwnd)); 00721 pwnd = PWCat(pcvr->pos.hwnd); // Known to be valid at this point. 00722 00723 /* 00724 * Don't z-order a destroyed window 00725 */ 00726 if (TestWF(pwnd, WFDESTROYED)) 00727 return TRUE; 00728 00729 UserAssert((HMPheFromObject(pwnd)->bFlags & HANDLEF_DESTROY) == 0); 00730 00731 pwndInsertAfter = PWInsertAfter(pcvr->pos.hwndInsertAfter); 00732 if (pcvr->pos.hwndInsertAfter != NULL && pwndInsertAfter == NULL) 00733 return TRUE; 00734 00735 if (pwndInsertAfter == PWND_BOTTOM) { 00736 00737 if (TestWF(pwnd, WFBOTTOMMOST)) 00738 return(pwnd->spwndNext == NULL); 00739 else 00740 return(pwnd == GetLastNonBottomMostWindow(pwnd, FALSE)); 00741 } 00742 00743 pwndPrev = pwnd->spwndParent->spwndChild; 00744 if (pwndInsertAfter == PWND_TOP) 00745 return pwndPrev == pwnd; 00746 00747 if (TestWF(pwndInsertAfter, WFDESTROYED)) 00748 return TRUE; 00749 00750 /* 00751 * When we compare the state of the window, we must use 00752 * the EVENTUAL state of the window that is moving, but 00753 * the CURRENT state of the window it's inserted behind. 00754 * 00755 * Prevent nonbottommost windows from going behind the bottommost one 00756 */ 00757 if (TestWF(pwndInsertAfter, WFBOTTOMMOST)) { 00758 pcvr->pos.hwndInsertAfter = HWInsertAfter(GetLastNonBottomMostWindow(pwnd, TRUE)); 00759 return FALSE; 00760 } 00761 00762 /* 00763 * If we are not topmost, but pwndInsertAfter is, OR 00764 * if we are topmost, but pwndInsertAfter is not, 00765 * we need to adjust pwndInsertAfter to be the last of 00766 * the topmost windows. 00767 */ 00768 bTopmost = TestWF(pwnd, WEFTOPMOST); 00769 00770 if (TestWF(pwnd, WFTOGGLETOPMOST)) 00771 bTopmost ^= LOBYTE(WEFTOPMOST); 00772 00773 if (bTopmost != (BYTE)TestWF(pwndInsertAfter, WEFTOPMOST)) { 00774 00775 pwndInsertAfter = GetLastTopMostWindow(); 00776 00777 /* 00778 * We're correctly positioned if we're already at the bottom 00779 */ 00780 if (pwndInsertAfter == pwnd) 00781 return TRUE; 00782 00783 pcvr->pos.hwndInsertAfter = HW(pwndInsertAfter); 00784 } 00785 00786 /* 00787 * Look for our previous window in the list... 00788 */ 00789 if (pwndPrev != pwnd) { 00790 00791 for ( ; pwndPrev != NULL; pwndPrev = pwndPrev->spwndNext) { 00792 00793 if (pwndPrev->spwndNext == pwnd) 00794 return pwndInsertAfter == pwndPrev; 00795 } 00796 00797 /* 00798 * If we get to here, pwnd is not in the sibling list. 00799 * REALLY BAD NEWS! 00800 */ 00801 UserAssert(FALSE); 00802 return TRUE; 00803 } 00804 00805 return FALSE; 00806 }

BOOL xxxCalcValidRects PSMWP  psmwp,
HWND *  phwndNewActive
 

Definition at line 821 of file swp.c.

References _FChildVisible(), _GetProp(), _GetWindow(), tagSMWP::acvr, BOOL, tagSMWP::ccvr, CFHREDRAW, CFVREDRAW, tagCVR::cxClientNew, tagCVR::cyClientNew, tagCVR::dxBlt, tagCVR::dyBlt, FALSE, FindValidWindowPos(), GetAppCompatFlags(), GetLastTopMostWindow(), GetLayeredWindow(), GetRect(), GRECT_CLIENT, GRECT_PARENTCOORDS, GRECT_WINDOW, HMRevalidateCatHandle, HW, HWq, IsStillWindowC(), IsTrayWindow(), NULL, OffsetRect(), tagCVR::pos, ppos, PROP_CHECKPOINT, PROPF_INTERNAL, PtoH, PW, PWNDDESKTOP, tagCVR::rcBlt, tagWND::rcClient, rcClientNew, rcClientOld, rcValidDst, rcValidSrc, tagWND::rcWindow, rcWindowNew, rcWindowOld, RevalidateHwnd, SetRectEmpty, SYSMET, TestCF, TestWF, TestwndChild, ThreadLock, ThreadLockAlways, ThreadUnlock, TRUE, UINT, ValidateZorder(), WEFTOOLWINDOW, WEFTOPMOST, WEFTRANSPARENT, WFBOTTOMMOST, WFCHILD, WFMINIMIZED, WFTOGGLETOPMOST, WFVISIBLE, WFWIN31COMPAT, WHERE_NOONE_CAN_SEE_ME, tagCVR::xClientNew, xxxCheckFullScreen(), xxxSendMessage(), and tagCVR::yClientNew.

Referenced by xxxEndDeferWindowPosEx().

00824 { 00825 PCVR pcvr; 00826 PWND pwnd; 00827 PWND pwndParent; 00828 HWND hwnd; 00829 HWND hwndNewActive = NULL; 00830 PWINDOWPOS ppos; 00831 BOOL fNoZorder; 00832 BOOL fForceNCCalcSize; 00833 NCCALCSIZE_PARAMS params; 00834 int cxSrc; 00835 int cySrc; 00836 int cxDst; 00837 int cyDst; 00838 int cmd; 00839 int ccvr; 00840 int xClientOld; 00841 int yClientOld; 00842 int cxClientOld; 00843 int cyClientOld; 00844 int xWindowOld; 00845 int yWindowOld; 00846 int cxWindowOld; 00847 int cyWindowOld; 00848 TL tlpwndParent; 00849 TL tlpwnd; 00850 00851 /* 00852 * Some of the windows in the SMWP list may be NULL at ths point 00853 * (removed because they'll be handled by their creator's thread) 00854 * so we've got to look for the first non-NULL window before we can 00855 * execute some of the tests below. FindValidWindowPos returns NULL if 00856 * the list has no valid windows in it. 00857 */ 00858 if ((ppos = FindValidWindowPos(psmwp)) == NULL) 00859 return FALSE; 00860 00861 UserAssert(PW(ppos->hwnd)); 00862 pwndParent = PW(ppos->hwnd)->spwndParent; 00863 00864 UserAssert(HMRevalidateCatHandle(PtoH(pwndParent))); 00865 00866 ThreadLock(pwndParent, &tlpwndParent); 00867 00868 fNoZorder = TRUE; 00869 00870 /* 00871 * Go through the SMWP list, enumerating each WINDOWPOS, and compute 00872 * its new window and client rectangles. 00873 */ 00874 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 00875 00876 /* 00877 * This loop may leave the critsect during each iteration so 00878 * we revalidate pos.hwnd before use. 00879 */ 00880 if ((hwnd = pcvr->pos.hwnd) == NULL) 00881 continue; 00882 00883 pwnd = RevalidateHwnd(hwnd); 00884 00885 if ((pwnd == NULL) || !IsStillWindowC(pcvr->pos.hwndInsertAfter)) { 00886 pcvr->pos.hwnd = NULL; 00887 pcvr->pos.flags = SWP_NOREDRAW | SWP_NOCHANGE; 00888 continue; 00889 } 00890 00891 ThreadLockAlways(pwnd, &tlpwnd); 00892 00893 /* 00894 * Used for 3.0 compatibility. 3.0 sent the NCCALCSIZE message even if 00895 * the size of the window wasn't changing. 00896 */ 00897 fForceNCCalcSize = FALSE; 00898 00899 if (!hwndNewActive && !(pcvr->pos.flags & SWP_NOACTIVATE)) 00900 hwndNewActive = HWq(pwnd); 00901 00902 if (!(pcvr->pos.flags & SWP_NOSENDCHANGING)) { 00903 00904 PWND pwndT; 00905 00906 xxxSendMessage(pwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pcvr->pos); 00907 00908 00909 /* 00910 * Don't let them change pcvr->pos.hwnd. It doesn't make sense 00911 * plus it'll mess us up. 00912 * I'm making this RIP_ERROR because we're too close to RTM (7/11/96) 00913 * just to make sure that we won't break anyone. This should be 00914 * changed to a RIP_WARNING after we ship. Use LOWORD to ignore 00915 * "changes" by NTVDM 00916 */ 00917 #if DBG 00918 if (LOWORD(pcvr->pos.hwnd) != LOWORD(hwnd)) { 00919 RIPMSG0(RIP_ERROR, 00920 "xxxCalcValidRects: Ignoring pcvr->pos.hwnd change by WM_WINDOWPOSCHANGING"); 00921 } 00922 #endif 00923 pcvr->pos.hwnd = hwnd; 00924 00925 /* 00926 * If the window sets again 'hwndInsertAfter' to HWND_NOTOPMOST 00927 * or HWND_TOPMOST, we need to set this member appropriately. 00928 * See CheckTopmost for details. 00929 */ 00930 if (pcvr->pos.hwndInsertAfter == HWND_NOTOPMOST) { 00931 if (TestWF(pwnd, WEFTOPMOST)) { 00932 00933 pwndT = GetLastTopMostWindow(); 00934 pcvr->pos.hwndInsertAfter = HW(pwndT); 00935 00936 if (pcvr->pos.hwndInsertAfter == pcvr->pos.hwnd) { 00937 pwndT = _GetWindow(pwnd, GW_HWNDPREV); 00938 pcvr->pos.hwndInsertAfter = HW(pwndT); 00939 } 00940 } else { 00941 pwndT = _GetWindow(pwnd, GW_HWNDPREV); 00942 pcvr->pos.hwndInsertAfter = HW(pwndT); 00943 } 00944 } else if (pcvr->pos.hwndInsertAfter == HWND_TOPMOST) { 00945 pcvr->pos.hwndInsertAfter = HWND_TOP; 00946 } 00947 } 00948 /* 00949 * make sure the rectangle still matches the window's region 00950 * 00951 * Remember the old window rectangle in parent coordinates 00952 */ 00953 xWindowOld = pwnd->rcWindow.left; 00954 yWindowOld = pwnd->rcWindow.top; 00955 if (pwndParent != PWNDDESKTOP(pwnd)) { 00956 xWindowOld -= pwndParent->rcClient.left; 00957 yWindowOld -= pwndParent->rcClient.top; 00958 } 00959 00960 00961 cxWindowOld = pwnd->rcWindow.right - pwnd->rcWindow.left; 00962 cyWindowOld = pwnd->rcWindow.bottom - pwnd->rcWindow.top; 00963 00964 /* 00965 * Assume the client is not moving or sizing 00966 */ 00967 pcvr->pos.flags |= SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE; 00968 00969 if (!(pcvr->pos.flags & SWP_NOMOVE)) { 00970 00971 if (pcvr->pos.x == xWindowOld && pcvr->pos.y == yWindowOld) 00972 pcvr->pos.flags |= SWP_NOMOVE; 00973 00974 00975 #ifdef USE_MIRRORING 00976 /* 00977 * Since we are comparing client coordinates to see whether 00978 * to move the window or not : 00979 * We've to check if the parent of the window-to-be-positioned is RTL 00980 * mirrored, then let's measure the client old x-coordinate from 00981 * the right visual edge. This is because the position of a window 00982 * is mirrored in the parent client area if the parent is RTL mirrored. 00983 */ 00984 if (TestWF(pwndParent, WEFLAYOUTRTL) && TestwndChild(pwnd) && 00985 (pwndParent->rcClient.right - pwnd->rcWindow.right + 1) != pcvr->pos.x) 00986 pcvr->pos.flags &= ~SWP_NOMOVE; 00987 #endif 00988 00989 if (TestWF(pwnd, WFMINIMIZED) && IsTrayWindow(pwnd)) { 00990 pcvr->pos.x = WHERE_NOONE_CAN_SEE_ME; 00991 pcvr->pos.y = WHERE_NOONE_CAN_SEE_ME; 00992 } 00993 00994 } else { 00995 pcvr->pos.x = xWindowOld; 00996 pcvr->pos.y = yWindowOld; 00997 } 00998 00999 if (!(pcvr->pos.flags & SWP_NOSIZE)) { 01000 01001 /* 01002 * Don't allow an invalid window rectangle. 01003 * BOGUS HACK: For Norton Antivirus, they call 01004 * MoveWindow at WM_CREATE Time EVEN though 01005 * the window is minimzed, but they assume its 01006 * restored at WM_CREATE time.... B#11185, t-arthb 01007 */ 01008 if (TestWF(pwnd, WFMINIMIZED) && 01009 _GetProp(pwnd, PROP_CHECKPOINT, PROPF_INTERNAL)) { 01010 01011 pcvr->pos.cx = SYSMET(CXMINIMIZED); 01012 pcvr->pos.cy = SYSMET(CYMINIMIZED); 01013 01014 } else { 01015 if (pcvr->pos.cx < 0) 01016 pcvr->pos.cx = 0; 01017 01018 if (pcvr->pos.cy < 0) 01019 pcvr->pos.cy = 0; 01020 } 01021 01022 if (pcvr->pos.cx == cxWindowOld && pcvr->pos.cy == cyWindowOld) { 01023 pcvr->pos.flags |= SWP_NOSIZE; 01024 if (!TestWF(pwnd, WFWIN31COMPAT)) 01025 fForceNCCalcSize = TRUE; 01026 } 01027 } else { 01028 pcvr->pos.cx = cxWindowOld; 01029 pcvr->pos.cy = cyWindowOld; 01030 } 01031 01032 #ifdef USE_MIRRORING 01033 if (TestWF(pwndParent, WEFLAYOUTRTL) && TestwndChild(pwnd) && (pwndParent != PWNDDESKTOP(pwnd))) { 01034 if (!(pcvr->pos.flags & SWP_NOMOVE)) { 01035 pcvr->pos.x = (pwndParent->rcClient.right - pwndParent->rcClient.left) - (pcvr->pos.x + pcvr->pos.cx); 01036 } else { 01037 if (!(pcvr->pos.flags & SWP_NOSIZE)) { 01038 pcvr->pos.x -= (pcvr->pos.cx - cxWindowOld); 01039 } 01040 } 01041 } 01042 #endif 01043 01044 /* 01045 * If showing and already visible, or hiding and already hidden, 01046 * turn off the appropriate bit. 01047 */ 01048 if (TestWF(pwnd, WFVISIBLE)) { 01049 pcvr->pos.flags &= ~SWP_SHOWWINDOW; 01050 } else { 01051 pcvr->pos.flags &= ~SWP_HIDEWINDOW; 01052 01053 /* 01054 * If hidden, and we're NOT showing, then we won't be drawing, 01055 * no matter what else is going on. 01056 */ 01057 if (!(pcvr->pos.flags & SWP_SHOWWINDOW)) 01058 pcvr->pos.flags |= SWP_NOREDRAW; 01059 } 01060 01061 /* 01062 * Muck with the zorder for bottommost windows, again 01063 * See comment in DeferWindowPos 01064 */ 01065 if (TestWF(pwnd, WFBOTTOMMOST)) { 01066 pcvr->pos.flags &= ~SWP_NOZORDER; 01067 pcvr->pos.hwndInsertAfter = HWND_BOTTOM; 01068 } 01069 01070 /* 01071 * If we're Z-ordering, we can try to remove the Z order 01072 * bit, as long as all previous windows in the WINDOWPOS list 01073 * have SWP_NOZORDER set. 01074 * 01075 * The reason we don't do this for each window individually 01076 * is that a window's eventual Z order depends on changes that 01077 * may have occured on windows earlier in the WINDOWPOS list, 01078 * so we can only call ValidateZorder if none of the previous 01079 * windows have changed. 01080 */ 01081 if (fNoZorder && !(pcvr->pos.flags & SWP_NOZORDER)) { 01082 01083 /* 01084 * If the TOPMOST bit is changing, the Z order is "changing", 01085 * so don't clear the bit even if it's in the right place in the 01086 * list. 01087 */ 01088 fNoZorder = FALSE; 01089 if (!TestWF(pwnd, WFTOGGLETOPMOST) && ValidateZorder(pcvr)) { 01090 fNoZorder = TRUE; 01091 pcvr->pos.flags |= SWP_NOZORDER; 01092 } 01093 } 01094 01095 /* 01096 * If no change is occuring, or if a parent is invisible, 01097 * we won't be redrawing. 01098 */ 01099 if (!(pcvr->pos.flags & SWP_NOREDRAW)) { 01100 if ((pcvr->pos.flags & SWP_CHANGEMASK) == SWP_NOCHANGE || 01101 !_FChildVisible(pwnd)) { 01102 pcvr->pos.flags |= SWP_NOREDRAW; 01103 } 01104 } 01105 01106 /* 01107 * BACKWARD COMPATIBILITY HACK 01108 * 01109 * In 3.0, if a window was moving but not sizing, we'd send the 01110 * WM_NCCALCSIZE message anyhow. Lotus Notes 2.1 depends on this 01111 * in order to move its "navigation bar" when the main window moves. 01112 */ 01113 if (!(pcvr->pos.flags & SWP_NOMOVE) && 01114 !TestWF(pwnd, WFWIN31COMPAT) && 01115 (GetAppCompatFlags(NULL) & GACF_NCCALCSIZEONMOVE)) { 01116 01117 fForceNCCalcSize = TRUE; 01118 } 01119 01120 /* 01121 * If the window rect is sizing, or if the frame has changed, 01122 * send the WM_NCCALCSIZE message and deal with valid areas. 01123 */ 01124 if (((pcvr->pos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) != SWP_NOSIZE) || 01125 fForceNCCalcSize) { 01126 01127 WINDOWPOS pos; 01128 01129 /* 01130 * check for full screen main app window 01131 */ 01132 if (!TestWF(pwnd, WFCHILD) && !TestWF(pwnd, WEFTOOLWINDOW)) { 01133 xxxCheckFullScreen(pwnd, (PSIZERECT)&pcvr->pos.x); 01134 } 01135 01136 /* 01137 * Set up NCCALCSIZE message parameters (in parent coords) 01138 * wParam = fClientOnly = TRUE 01139 * lParam = &params 01140 */ 01141 pos = pcvr->pos; // Make a local stack copy 01142 params.lppos = &pos; 01143 01144 /* 01145 * params.rgrc[0] = rcWindowNew = New window rectangle 01146 * params.rgrc[1] = rcWindowOld = Old window rectangle 01147 * params.rgrc[2] = rcClientOld = Old client rectangle 01148 */ 01149 #define rcWindowNew params.rgrc[0] 01150 #define rcWindowOld params.rgrc[1] 01151 #define rcClientOld params.rgrc[2] 01152 01153 /* 01154 * Set up rcWindowNew in parent relative coordinates 01155 */ 01156 rcWindowNew.left = pcvr->pos.x; 01157 rcWindowNew.right = rcWindowNew.left + pcvr->pos.cx; 01158 rcWindowNew.top = pcvr->pos.y; 01159 rcWindowNew.bottom = rcWindowNew.top + pcvr->pos.cy; 01160 01161 /* 01162 * Set up rcWindowOld in parent relative coordinates 01163 */ 01164 GetRect(pwnd, &rcWindowOld, GRECT_WINDOW | GRECT_PARENTCOORDS); 01165 01166 /* 01167 * Set up rcClientOld in parent relative coordinates 01168 */ 01169 GetRect(pwnd, &rcClientOld, GRECT_CLIENT | GRECT_PARENTCOORDS); 01170 01171 /* 01172 * Keep around a copy of the old client position 01173 */ 01174 xClientOld = rcClientOld.left; 01175 cxClientOld = rcClientOld.right - rcClientOld.left; 01176 yClientOld = rcClientOld.top; 01177 cyClientOld = rcClientOld.bottom - rcClientOld.top; 01178 01179 cmd = (UINT)xxxSendMessage(pwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params); 01180 01181 if (!IsStillWindowC(pcvr->pos.hwndInsertAfter)) { 01182 ThreadUnlock(&tlpwnd); 01183 ThreadUnlock(&tlpwndParent); 01184 return FALSE; 01185 } 01186 01187 /* 01188 * Upon return from NCCALCSIZE: 01189 * 01190 * params.rgrc[0] = rcClientNew = New client rect 01191 * params.rgrc[1] = rcValidDst = Destination valid rectangle 01192 * params.rgrc[2] = rcValidSrc = Source valid rectangle 01193 */ 01194 #undef rcWindowNew 01195 #undef rcWindowOld 01196 #undef rcClientOld 01197 01198 #define rcClientNew params.rgrc[0] 01199 #define rcValidDst params.rgrc[1] 01200 #define rcValidSrc params.rgrc[2] 01201 01202 /* 01203 * Calculate the distance the window contents are 01204 * moving. If 0 or an invalid value was returned 01205 * from the WM_NCCALCSIZE message, assume the 01206 * entire client area is valid and top-left aligned. 01207 */ 01208 if (cmd < WVR_MINVALID || cmd > WVR_MAXVALID) { 01209 01210 /* 01211 * We don't need to copy rcValidSrc to rcClientOld, 01212 * because it's already stored in rgrc[2]. 01213 * 01214 * rcValidSrc = rcClientOld 01215 */ 01216 rcValidDst = rcClientNew; 01217 01218 cmd = WVR_ALIGNTOP | WVR_ALIGNLEFT; 01219 } 01220 01221 /* 01222 * Calculate the distance we'll be shifting bits... 01223 */ 01224 #ifdef USE_MIRRORING 01225 if (TestWF(pwnd, WEFLAYOUTRTL)) { 01226 pcvr->dxBlt = rcValidDst.right - rcValidSrc.right; 01227 } else 01228 #endif 01229 { 01230 pcvr->dxBlt = rcValidDst.left - rcValidSrc.left; 01231 } 01232 pcvr->dyBlt = rcValidDst.top - rcValidSrc.top; 01233 01234 /* 01235 * Calculate new client rect size and position 01236 */ 01237 pcvr->xClientNew = rcClientNew.left; 01238 pcvr->yClientNew = rcClientNew.top; 01239 01240 pcvr->cxClientNew = rcClientNew.right - rcClientNew.left; 01241 pcvr->cyClientNew = rcClientNew.bottom - rcClientNew.top; 01242 01243 /* 01244 * Figure out whether the client rectangle is moving or sizing, 01245 * and diddle the appropriate bit if not. 01246 */ 01247 if (xClientOld != rcClientNew.left || yClientOld != rcClientNew.top) 01248 pcvr->pos.flags &= ~SWP_NOCLIENTMOVE; 01249 01250 if (cxClientOld != pcvr->cxClientNew || cyClientOld != pcvr->cyClientNew) { 01251 pcvr->pos.flags &= ~SWP_NOCLIENTSIZE; 01252 } 01253 01254 /* 01255 * If the caller doesn't want us to save any bits, then don't. 01256 */ 01257 if (pcvr->pos.flags & SWP_NOCOPYBITS) { 01258 AllInvalid: 01259 01260 /* 01261 * The entire window is invalid: Set the blt rectangle 01262 * to empty, to ensure nothing gets bltted. 01263 */ 01264 SetRectEmpty(&pcvr->rcBlt); 01265 ThreadUnlock(&tlpwnd); 01266 continue; 01267 } 01268 01269 /* 01270 * If this is a transparent window, be sure to invalidate 01271 * everything, because only some of the window's bits are 01272 * blittable. 01273 */ 01274 if (TestWF(pwnd, WEFTRANSPARENT)) 01275 goto AllInvalid; 01276 01277 /* 01278 * We never want to try to copy screen bits for a redirected or a 01279 * layered window. For child windows we may be able to do the 01280 * copy in our redirection bitmap, but that would add a bunch of 01281 * work in zzzBltValidBits. We should consider that for later. 01282 */ 01283 if (GetLayeredWindow(pwnd) != NULL) 01284 goto AllInvalid; 01285 01286 /* 01287 * If both client and window did not change size, the frame didn't 01288 * change, and the blt rectangle moved the same distance as the 01289 * rectangle, then the entire window area is valid. 01290 */ 01291 if (((pcvr->pos.flags & 01292 (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_FRAMECHANGED)) 01293 == (SWP_NOSIZE | SWP_NOCLIENTSIZE)) && 01294 pcvr->dxBlt == (pcvr->pos.x - xWindowOld) && 01295 pcvr->dyBlt == (pcvr->pos.y - yWindowOld)) { 01296 01297 goto AllValid; 01298 } 01299 01300 /* 01301 * Now compute the valid blt rectangle. 01302 * 01303 * Check for horz or vert client size changes 01304 * 01305 * NOTE: Assumes WVR_REDRAW == WVR_HREDRAW | WVR_VREDRAW 01306 */ 01307 if (cxClientOld != pcvr->cxClientNew) { 01308 01309 if ((cmd & WVR_HREDRAW) || TestCF(pwnd, CFHREDRAW)) 01310 goto AllInvalid; 01311 } 01312 01313 if (cyClientOld != pcvr->cyClientNew) { 01314 01315 if ((cmd & WVR_VREDRAW) || TestCF(pwnd, CFVREDRAW)) 01316 goto AllInvalid; 01317 } 01318 01319 cxSrc = rcValidSrc.right - rcValidSrc.left; 01320 cySrc = rcValidSrc.bottom - rcValidSrc.top; 01321 01322 cxDst = rcValidDst.right - rcValidDst.left; 01323 cyDst = rcValidDst.bottom - rcValidDst.top; 01324 01325 #ifdef USE_MIRRORING 01326 if ((!!(cmd & WVR_ALIGNRIGHT)) ^ (!!TestWF(pwnd, WEFLAYOUTRTL))) 01327 rcValidDst.left += ((TestWF(pwnd, WEFLAYOUTRTL) && (cxSrc > cxDst)) ? (cxSrc-cxDst) : (cxDst - cxSrc)); 01328 #else 01329 if (cmd & WVR_ALIGNRIGHT) 01330 rcValidDst.left += (cxDst - cxSrc); 01331 #endif 01332 01333 if (cmd & WVR_ALIGNBOTTOM) 01334 rcValidDst.top += (cyDst - cySrc); 01335 01336 /* 01337 * Superimpose the source on the destination, and intersect 01338 * the rectangles. This is done by looking at the 01339 * extent of the rectangles, and pinning as appropriate. 01340 */ 01341 01342 if (cxSrc < cxDst) 01343 rcValidDst.right = rcValidDst.left + cxSrc; 01344 01345 if (cySrc < cyDst) 01346 rcValidDst.bottom = rcValidDst.top + cySrc; 01347 01348 /* 01349 * Finally map the blt rectangle to screen coordinates. 01350 */ 01351 pcvr->rcBlt = rcValidDst; 01352 if (pwndParent != PWNDDESKTOP(pwnd)) { 01353 01354 OffsetRect( 01355 &pcvr->rcBlt, 01356 pwndParent->rcClient.left, 01357 pwndParent->rcClient.top); 01358 } 01359 } else { // if !SWP_NOSIZE or SWP_FRAMECHANGED 01360 01361 AllValid: 01362 01363 /* 01364 * No client size change: Blt the entire window, 01365 * including the frame. Offset everything by 01366 * the distance the window rect changed. 01367 */ 01368 if (pcvr->pos.flags & SWP_NOCOPYBITS) { 01369 SetRectEmpty(&pcvr->rcBlt); 01370 } else { 01371 pcvr->rcBlt.left = pcvr->pos.x; 01372 pcvr->rcBlt.top = pcvr->pos.y; 01373 01374 if (pwndParent != PWNDDESKTOP(pwnd)) { 01375 pcvr->rcBlt.left += pwndParent->rcClient.left; 01376 pcvr->rcBlt.top += pwndParent->rcClient.top; 01377 } 01378 01379 pcvr->rcBlt.right = pcvr->rcBlt.left + pcvr->pos.cx; 01380 pcvr->rcBlt.bottom = pcvr->rcBlt.top + pcvr->pos.cy; 01381 } 01382 01383 /* 01384 * Offset everything by the distance the window moved. 01385 */ 01386 #ifdef USE_MIRRORING 01387 if (TestWF(pwnd, WEFLAYOUTRTL)) { 01388 pcvr->dxBlt = (pcvr->pos.x + pcvr->pos.cx) - (xWindowOld + cxWindowOld); 01389 } else 01390 #endif 01391 { 01392 pcvr->dxBlt = pcvr->pos.x - xWindowOld; 01393 } 01394 01395 pcvr->dyBlt = pcvr->pos.y - yWindowOld; 01396 01397 /* 01398 * If we're moving, we need to set up the client. 01399 */ 01400 if (!(pcvr->pos.flags & SWP_NOMOVE)) { 01401 pcvr->pos.flags &= ~SWP_NOCLIENTMOVE; 01402 01403 pcvr->xClientNew = pwnd->rcClient.left + pcvr->dxBlt; 01404 pcvr->yClientNew = pwnd->rcClient.top + pcvr->dyBlt; 01405 if (pwndParent != PWNDDESKTOP(pwnd)) { 01406 pcvr->xClientNew -= pwndParent->rcClient.left; 01407 pcvr->yClientNew -= pwndParent->rcClient.top; 01408 } 01409 01410 pcvr->cxClientNew = pwnd->rcClient.right - pwnd->rcClient.left; 01411 pcvr->cyClientNew = pwnd->rcClient.bottom - pwnd->rcClient.top; 01412 } 01413 } 01414 01415 ThreadUnlock(&tlpwnd); 01416 01417 } // for (... pcvr ...) 01418 01419 ThreadUnlock(&tlpwndParent); 01420 *phwndNewActive = hwndNewActive; 01421 01422 return TRUE; 01423 }

BOOL xxxCheckFullScreen PWND  pwnd,
PSIZERECT  psrc
 

Definition at line 5305 of file swp.c.

References _MonitorFromRect(), _MonitorFromWindow(), tagCLS::atomClassName, BOOL, CheckLock, ClrWF, tagDISPLAYINFO::cMonitors, tagSIZERECT::cx, tagSIZERECT::cy, FALSE, gatomConsoleClass, GetPrimaryMonitor(), GetWindowBorders(), gpDispInfo, IsMaxedRect(), LOBYTE, min, tagWND::pcls, tagMONITOR::rcMonitor, tagDISPLAYINFO::rcScreen, RECTFromSIZERECT(), SetWF, SYSMET, TestWF, ThreadLockAlways, ThreadUnlock, TRUE, WEFTOOLWINDOW, WFBORDERMASK, WFCAPTION, WFCHILD, WFFULLSCREEN, WFMAXBOX, WFMAXIMIZED, WFREALLYMAXIMIZABLE, WFWIN40COMPAT, tagSIZERECT::x, xxxAddFullScreen(), xxxRemoveFullScreen(), and tagSIZERECT::y.

Referenced by xxxCalcValidRects(), and xxxCreateWindowEx().

05308 { 05309 BOOL fYielded = FALSE; 05310 PMONITOR pMonitor; 05311 PMONITOR pMonitorPrimary; 05312 TL tlpMonitor; 05313 RECT rc; 05314 BOOL fIsPrimary; 05315 05316 05317 CheckLock(pwnd); 05318 05319 /* 05320 * SINCE THIS IS ONLY CALLED IN 2 PLACES, make the checks there 05321 * instead of the overhead of calling this function in time critical 05322 * places. 05323 * 05324 * If 3 or more places call it, put the child/toolwindow checks here 05325 */ 05326 UserAssert(!TestWF(pwnd, WFCHILD)); 05327 UserAssert(!TestWF(pwnd, WEFTOOLWINDOW)); 05328 05329 pMonitorPrimary = GetPrimaryMonitor(); 05330 if (gpDispInfo->cMonitors == 1) { 05331 pMonitor = pMonitorPrimary; 05332 } else { 05333 /* 05334 * In multiple monitor mode, windows that take up the entire 05335 * virtual screen are not considered 'full screen'. 'Full screen' 05336 * means full single monitor only. This detection is so that any 05337 * docked bars--tray, office'95 tools--can get out of the way for 05338 * the application. 05339 * 05340 * There are only three types of windows that ought to go full 05341 * virtual screen. None of them need the tray et al. to get out of 05342 * the way: 05343 * (1) Normal app windows that want a lot of space 05344 * * Those guys just activate and deactivate normally. 05345 * (2) Desktop windows 05346 * * Shell, User desktop sit behind everything else. 05347 * (3) Screen savers, demos, etc. 05348 * * These guys should be WS_EX_TOPMOST to ensure they sit 05349 * over everybody. 05350 */ 05351 if (IsMaxedRect(&gpDispInfo->rcScreen, psrc)) 05352 return fYielded; 05353 05354 RECTFromSIZERECT(&rc, psrc); 05355 pMonitor = _MonitorFromRect(&rc, MONITOR_DEFAULTTOPRIMARY); 05356 } 05357 05358 fIsPrimary = (pMonitor == pMonitorPrimary); 05359 ThreadLockAlways(pMonitor, &tlpMonitor); 05360 05361 if (IsMaxedRect(&pMonitor->rcWork, psrc)) { 05362 if (TestWF(pwnd, WFMAXIMIZED)) { 05363 SetWF(pwnd, WFREALLYMAXIMIZABLE); 05364 05365 if (gpDispInfo->cMonitors > 1) { 05366 /* 05367 * BUGBUG: Check if app is before 4.1? 05368 */ 05369 05370 /* 05371 * This is for XL '95 going fullscreen when already maxed. It 05372 * always uses the primary display. Let's hack them, and any 05373 * other old app that tries to move its truly maximized window. 05374 * They will be clipped otherwise by our fake regional stuff. 05375 */ 05376 PMONITOR pMonitorReal; 05377 05378 pMonitorReal = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY); 05379 if (pMonitorReal != pMonitor && fIsPrimary) { 05380 /* 05381 * Transfer over the shape to the REAL monitor. 05382 */ 05383 psrc->x += pMonitorReal->rcMonitor.left; 05384 psrc->y += pMonitorReal->rcMonitor.top; 05385 psrc->cx -= (pMonitor->rcMonitor.right - pMonitor->rcMonitor.left) + 05386 (pMonitorReal->rcMonitor.right - pMonitorReal->rcMonitor.left); 05387 05388 psrc->cy -= (pMonitor->rcMonitor.bottom - pMonitor->rcMonitor.top) + 05389 (pMonitorReal->rcMonitor.bottom - pMonitorReal->rcMonitor.top); 05390 05391 ThreadUnlock(&tlpMonitor); 05392 pMonitor = pMonitorReal; 05393 fIsPrimary = FALSE; 05394 ThreadLockAlways(pMonitor, &tlpMonitor); 05395 } 05396 } 05397 } 05398 05399 if ( TestWF(pwnd, WFMAXIMIZED) && 05400 TestWF(pwnd, WFMAXBOX) && 05401 (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION))) { 05402 05403 if ( psrc->y + SYSMET(CYCAPTION) <= pMonitor->rcMonitor.top && 05404 psrc->y + psrc->cy >= pMonitor->rcMonitor.bottom) { 05405 05406 if (!TestWF(pwnd, WFFULLSCREEN)) { 05407 /* 05408 * Only want to do full screen stuff on the tray 05409 * monitor. 05410 */ 05411 fYielded = xxxAddFullScreen(pwnd, pMonitor); 05412 } 05413 } else { 05414 int iRight; 05415 int iBottom; 05416 int dxy; 05417 05418 if (TestWF(pwnd, WFFULLSCREEN)) { 05419 fYielded = xxxRemoveFullScreen(pwnd, pMonitor); 05420 } 05421 05422 /* 05423 * Despite the code in GetMinMaxInfo() to fix up 05424 * the max rect, we still have to hack old apps. 05425 * Word '95 & XL '95 do weird things when going to/from 05426 * full screen when maximized already. 05427 * 05428 * NOTE: you can have more than one docked bar on a 05429 * monitor. Win '95 code doesn't work right in that 05430 * case. 05431 */ 05432 dxy = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); 05433 dxy *= SYSMET(CXBORDER); 05434 05435 psrc->x = pMonitor->rcWork.left - dxy; 05436 psrc->y = pMonitor->rcWork.top - dxy; 05437 05438 dxy *= 2; 05439 iRight = 05440 pMonitor->rcWork.right - pMonitor->rcWork.left + dxy; 05441 iBottom = 05442 pMonitor->rcWork.bottom - pMonitor->rcWork.top + dxy; 05443 05444 /* 05445 * Let console windows maximize smaller than defaults. 05446 */ 05447 if (pwnd->pcls->atomClassName == gatomConsoleClass) { 05448 psrc->cx = min(iRight, psrc->cx); 05449 psrc->cy = min(iBottom, psrc->cy); 05450 } else { 05451 psrc->cx = iRight; 05452 05453 /* 05454 * B#14012 save QuickLink II that wants 4 pixels hanging off 05455 * the screen for every edge except the bottom edge, which 05456 * they only want to overhang by 2 pixels -- jeffbog 5/17/95 05457 * 05458 * BUT THIS CODE DOESN'T WORK FOR MULTIPLE MONITORS, so don't 05459 * do it on secondary dudes. Else, XL '95 flakes out. 05460 */ 05461 if (fIsPrimary && !TestWF(pwnd, WFWIN40COMPAT)) { 05462 psrc->cy = min(iBottom, psrc->cy); 05463 } else { 05464 psrc->cy = iBottom; 05465 } 05466 } 05467 } 05468 05469 } else if (IsMaxedRect(&pMonitor->rcMonitor, psrc)) { 05470 fYielded = xxxAddFullScreen(pwnd, pMonitor); 05471 } 05472 } else { 05473 if (TestWF(pwnd, WFMAXIMIZED)) { 05474 ClrWF(pwnd, WFREALLYMAXIMIZABLE); 05475 } 05476 05477 fYielded = xxxRemoveFullScreen(pwnd, pMonitor); 05478 } 05479 05480 ThreadUnlock(&tlpMonitor); 05481 return fYielded; 05482 }

BOOL xxxEndDeferWindowPosEx PSMWP  psmwp,
BOOL  fAsync
 

Definition at line 4773 of file swp.c.

References tagSMWP::acvr, AsyncWindowPos(), tagSMWP::bHandle, BOOL, tagSMWP::bShellNotify, tagSMWP::ccvr, CheckLock, ClrWF, tagTHREADINFO::cVisWindows, DBGCheskSMWP, DestroySMWP(), DSP_ENUMCLIPPEDCHILDREN, FALSE, FindValidWindowPos(), gptiForeground, tagWND::head, IsWinEventNotifyDeferredOK, NULL, tagCVR::pos, PostShellHookMessages(), PtiCurrent, PW, PWNDDESKTOP, RestoreForegroundActivate(), RevalidateHwnd, STW_SAME, ThreadLockAlwaysWithPti, ThreadLockPoolCleanup, ThreadLockWithPti, ThreadUnlock, ThreadUnlockPoolCleanup, TIF_ALLOWFOREGROUNDACTIVATE, TRUE, UINT, ValidateSmwp(), WFNONCPAINT, xxxCalcValidRects(), xxxCallHook(), xxxDoSyncPaint(), xxxSendChangedMsgs(), xxxSetTrayWindow(), xxxSwpActivate(), ZOrderByOwner(), and zzzBltValidBits().

Referenced by NtUserEndDeferWindowPosEx(), xxxArrangeIconicWindows(), xxxDesktopRecalc(), xxxMinMaximize(), xxxProcessSetWindowPosEvent(), xxxSetWindowPos(), and xxxSetWindowRgn().

04776 { 04777 PWND pwndNewActive; 04778 PWND pwndParent; 04779 PWND pwndActive; 04780 PWND pwndActivePrev; 04781 HWND hwndNewActive; 04782 PWINDOWPOS pwp; 04783 BOOL fClearBits; 04784 BOOL fSyncPaint; 04785 UINT cVisWindowsPrev; 04786 PTHREADINFO ptiCurrent = PtiCurrent(); 04787 TL tlpwndNewActive; 04788 TL tlpwndParent; 04789 TL tlcuSMWP; 04790 BOOL fForegroundPrev; 04791 04792 UserAssert(IsWinEventNotifyDeferredOK()); 04793 04794 DBGCheskSMWP(psmwp); 04795 if (psmwp->bHandle) { 04796 CheckLock(psmwp); 04797 } 04798 04799 /* 04800 * Validate the window pos structures and find a window to activate. 04801 */ 04802 if ((psmwp->ccvr != 0) && ValidateSmwp(psmwp, &fSyncPaint)) { 04803 04804 if ((pwp = FindValidWindowPos(psmwp)) == NULL) 04805 goto lbFinished; 04806 04807 /* 04808 * Make sure to stop at the mother desktop window. In Win95 04809 * a SetWindowPos() on a desktop window will have a NULL parent 04810 * window. This is not true in NT, but our mother desktop 04811 * window does have a NULL rpdesk, so check it too. 04812 */ 04813 UserAssert(PW(pwp->hwnd)); 04814 pwndParent = PW(pwp->hwnd)->spwndParent; 04815 if (pwndParent == NULL || pwndParent->head.rpdesk == NULL) 04816 goto lbFinished; 04817 04818 /* 04819 * Usually all window positioning happens synchronously across threads. 04820 * This is because apps expect that behavior now - if it was async, 04821 * callers could not expect the state to be set once the api returned. 04822 * This is not the semantics of SetWindowPos(). The downside of this 04823 * synchronicity is that a SetWindowPos() on an hwnd created by another 04824 * thread will cause the caller to wait for that thread - even if that 04825 * thread is hung. That's what you get. 04826 * 04827 * We don't want task manager to hang though, no matter who else is 04828 * hung, so when taskman calls, it calls a special entry point for 04829 * tiling / cascading, which does SetWindowPos() asynchronously - 04830 * by posting an event in each thread's queue that makes it set its 04831 * own window position - that way if the thread is hung, who cares - 04832 * it doesn't effect taskman. 04833 * 04834 * Do async window pos positioning before zorder by owner so that 04835 * we retain any cross thread ownership relationships synchronously. 04836 */ 04837 if (fAsync) { 04838 AsyncWindowPos(psmwp); 04839 } 04840 04841 /* 04842 * If needed, Z order the windows by owner. 04843 * This may grow the SMWP, if new CVRs are added. 04844 */ 04845 if (pwndParent == PWNDDESKTOP(pwndParent)) { 04846 04847 if ((psmwp = ZOrderByOwner(psmwp)) == NULL) { 04848 return FALSE; 04849 } 04850 } 04851 04852 ThreadLockAlwaysWithPti(ptiCurrent, pwndParent, &tlpwndParent); 04853 ThreadLockPoolCleanup(ptiCurrent, psmwp, &tlcuSMWP, DestroySMWP); 04854 04855 /* 04856 * Calc new window positions. 04857 */ 04858 if (xxxCalcValidRects(psmwp, &hwndNewActive)) { 04859 04860 int i; 04861 04862 pwndNewActive = RevalidateHwnd(hwndNewActive); 04863 04864 ThreadLockWithPti(ptiCurrent, pwndNewActive, &tlpwndNewActive); 04865 04866 cVisWindowsPrev = ptiCurrent->cVisWindows; 04867 fForegroundPrev = (ptiCurrent == gptiForeground); 04868 04869 /* 04870 * The call to zzzBltValidBits will leave the critical section 04871 * if there are any notifications to make. 04872 */ 04873 UserAssert(IsWinEventNotifyDeferredOK()); 04874 if (!zzzBltValidBits(psmwp)) 04875 fSyncPaint = FALSE; 04876 UserAssert(IsWinEventNotifyDeferredOK()); 04877 04878 if (psmwp->bShellNotify) { 04879 for (i = psmwp->ccvr; i-- != 0; ) { 04880 /* 04881 * Loop through the windows, looking for notifications. 04882 */ 04883 04884 if (0 == (psmwp->acvr[i].pos.flags & SWP_NOTIFYALL)) 04885 continue; 04886 04887 if (psmwp->acvr[i].pos.flags & SWP_NOTIFYCREATE) { 04888 PostShellHookMessages(HSHELL_WINDOWCREATED, 04889 (LPARAM)psmwp->acvr[i].pos.hwnd); 04890 04891 xxxCallHook(HSHELL_WINDOWCREATED, 04892 (WPARAM)psmwp->acvr[i].pos.hwnd, 04893 (LPARAM)0, 04894 WH_SHELL); 04895 } 04896 04897 if (psmwp->acvr[i].pos.flags & SWP_NOTIFYDESTROY) { 04898 PostShellHookMessages(HSHELL_WINDOWDESTROYED, 04899 (LPARAM)psmwp->acvr[i].pos.hwnd); 04900 04901 xxxCallHook(HSHELL_WINDOWDESTROYED, 04902 (WPARAM)psmwp->acvr[i].pos.hwnd, 04903 (LPARAM)0, 04904 WH_SHELL); 04905 } 04906 04907 if (psmwp->acvr[i].pos.flags & SWP_NOTIFYACTIVATE) { 04908 PWND pwnd = RevalidateHwnd(psmwp->acvr[i].pos.hwnd); 04909 if (pwnd != NULL){ 04910 TL tlpwnd; 04911 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); 04912 xxxSetTrayWindow(pwnd->head.rpdesk, pwnd, NULL); 04913 ThreadUnlock(&tlpwnd); 04914 } 04915 } 04916 04917 if (psmwp->acvr[i].pos.flags & SWP_NOTIFYFS) { 04918 xxxSetTrayWindow(ptiCurrent->rpdesk, STW_SAME, NULL); 04919 } 04920 } 04921 } 04922 04923 04924 /* 04925 * If this process went from some windows to no windows visible 04926 * and it was in the foreground, then let its next activate 04927 * come to the foreground. 04928 */ 04929 if (fForegroundPrev && cVisWindowsPrev && !ptiCurrent->cVisWindows) { 04930 04931 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 04932 TAGMSG1(DBGTAG_FOREGROUND, "xxxEndDeferWindowPosEx set TIF %#p", ptiCurrent); 04933 04934 /* 04935 * Also if any apps were in the middle of starting when 04936 * this happened, allow them to foreground activate again. 04937 */ 04938 RestoreForegroundActivate(); 04939 } 04940 04941 /* 04942 * Deal with any activation... 04943 */ 04944 fClearBits = FALSE; 04945 if (pwndNewActive != NULL) 04946 fClearBits = xxxSwpActivate(pwndNewActive); 04947 04948 /* 04949 * Now draw frames and erase backgrounds of all the windows 04950 * involved. 04951 */ 04952 UserAssert(pwndParent); 04953 if (fSyncPaint) 04954 xxxDoSyncPaint(pwndParent, DSP_ENUMCLIPPEDCHILDREN); 04955 04956 ThreadUnlock(&tlpwndNewActive); 04957 04958 /* 04959 * If SwpActivate() set the NONCPAINT bits, clear them now. 04960 */ 04961 if (fClearBits) { 04962 04963 if (pwndActive = ptiCurrent->pq->spwndActive) 04964 ClrWF(pwndActive, WFNONCPAINT); 04965 04966 if (pwndActivePrev = ptiCurrent->pq->spwndActivePrev) 04967 ClrWF(pwndActivePrev, WFNONCPAINT); 04968 } 04969 04970 /* 04971 * Send WM_WINDOWPOSCHANGED messages 04972 */ 04973 xxxSendChangedMsgs(psmwp); 04974 } 04975 04976 ThreadUnlockPoolCleanup(ptiCurrent, &tlcuSMWP); 04977 ThreadUnlock(&tlpwndParent); 04978 } 04979 04980 lbFinished: 04981 04982 /* 04983 * All done. Free everything up and return. 04984 */ 04985 DestroySMWP(psmwp); 04986 return TRUE; 04987 }

VOID xxxHandleWindowPosChanged PWND  pwnd,
PWINDOWPOS  ppos
 

Definition at line 3381 of file swp.c.

References CheckLock, FALSE, ppos, PWNDDESKTOP, tagWND::rcClient, tagWND::spwndParent, TestWF, VOID(), WFMAXIMIZED, WFMINIMIZED, xxxSendMessage(), and xxxSendSizeMessage().

Referenced by xxxDefWindowProc().

03384 { 03385 CheckLock(pwnd); 03386 03387 if (!(ppos->flags & SWP_NOCLIENTMOVE)) { 03388 POINT pt; 03389 PWND pwndParent; 03390 03391 pt.x = pwnd->rcClient.left; 03392 pt.y = pwnd->rcClient.top; 03393 03394 pwndParent = pwnd->spwndParent; 03395 UserAssert(pwndParent); 03396 03397 if (pwndParent != PWNDDESKTOP(pwnd)) { 03398 pt.x -= pwndParent->rcClient.left; 03399 pt.y -= pwndParent->rcClient.top; 03400 } 03401 03402 xxxSendMessage( 03403 pwnd, 03404 WM_MOVE, 03405 FALSE, 03406 MAKELONG(pt.x, pt.y)); 03407 } 03408 03409 if ((ppos->flags & SWP_STATECHANGE) || !(ppos->flags & SWP_NOCLIENTSIZE)) { 03410 03411 if (TestWF(pwnd, WFMINIMIZED)) 03412 xxxSendSizeMessage(pwnd, SIZEICONIC); 03413 else if (TestWF(pwnd, WFMAXIMIZED)) 03414 xxxSendSizeMessage(pwnd, SIZEFULLSCREEN); 03415 else 03416 xxxSendSizeMessage(pwnd, SIZENORMAL); 03417 } 03418 }

BOOL xxxMoveWindow PWND  pwnd,
int  x,
int  y,
int  cx,
int  cy,
BOOL  fRedraw
 

Definition at line 144 of file swp.c.

References BOOL, CheckLock, cy, MW_FLAGS_NOREDRAW, MW_FLAGS_REDRAW, NULL, PWNDDESKTOP, tagWND::spwndParent, TestWF, WFWIN31COMPAT, xxxSetWindowPos(), and xxxValidateRect().

Referenced by NtUserMoveWindow(), and xxxSBWndProc().

00151 { 00152 CheckLock(pwnd); 00153 00154 if ((pwnd == PWNDDESKTOP(pwnd)) || 00155 TestWF(pwnd, WFWIN31COMPAT) || 00156 (pwnd->spwndParent != PWNDDESKTOP(pwnd))) { 00157 00158 return xxxSetWindowPos( 00159 pwnd, 00160 NULL, 00161 x, 00162 y, 00163 cx, 00164 cy, 00165 (fRedraw ? MW_FLAGS_REDRAW : MW_FLAGS_NOREDRAW)); 00166 } else { 00167 00168 /* 00169 * BACKWARD COMPATIBILITY CODE FOR WIN 3.00 AND BELOW 00170 * 00171 * Everyone and their brother seems to depend on this behavior for 00172 * top-level windows. Specific examples are: 00173 * 00174 * AfterDark help window animation 00175 * Finale Speedy Note Editing 00176 * 00177 * If the window is a top-level window and fRedraw is FALSE, 00178 * we must call SetWindowPos with SWP_NOREDRAW CLEAR anyway so that 00179 * the frame and window background get drawn. We then validate the 00180 * entire client rectangle to avoid repainting that. 00181 */ 00182 BOOL fResult = xxxSetWindowPos(pwnd, 00183 NULL, 00184 x, 00185 y, 00186 cx, 00187 cy, 00188 MW_FLAGS_REDRAW); 00189 00190 if (!fRedraw) 00191 xxxValidateRect(pwnd, NULL); 00192 00193 return fResult; 00194 } 00195 }

VOID xxxProcessSetWindowPosEvent PSMWP  psmwpT  ) 
 

Definition at line 1884 of file swp.c.

References tagSMWP::acvr, tagSMWP::ccvr, FALSE, InternalBeginDeferWindowPos(), NULL, VOID(), and xxxEndDeferWindowPosEx().

Referenced by xxxProcessEventMessage().

01886 { 01887 PSMWP psmwp; 01888 01889 /* 01890 * Create a bonafide SMWP/CVR array that xxxEndDeferWindowPos can use 01891 * and later free. 01892 */ 01893 if ((psmwp = InternalBeginDeferWindowPos(psmwpT->ccvr)) == NULL) { 01894 UserFreePool(psmwpT); 01895 return; 01896 } 01897 01898 /* 01899 * Copy the contents of the temp SMWP/CVR array into the real one. 01900 */ 01901 RtlCopyMemory(psmwp->acvr, psmwpT->acvr, sizeof(CVR) * psmwpT->ccvr); 01902 psmwp->ccvr = psmwpT->ccvr; 01903 01904 /* 01905 * Complete the MultWindowPos operation now that we're on the correct 01906 * context. 01907 */ 01908 xxxEndDeferWindowPosEx(psmwp, FALSE); 01909 01910 /* 01911 * Free the temp SMWP/CVR array. 01912 */ 01913 UserFreePool(psmwpT); 01914 }

VOID xxxSendChangedMsgs PSMWP  psmwp  ) 
 

Definition at line 1669 of file swp.c.

References tagSMWP::acvr, tagSMWP::ccvr, FWINABLE, IsStillWindowC(), NULL, tagCVR::pos, RevalidateHwnd, ThreadLockAlways, ThreadUnlock, VOID(), WEF_USEPWNDTHREAD, xxxSendMessage(), and xxxWindowEvent().

Referenced by xxxEndDeferWindowPosEx().

01671 { 01672 PWND pwnd; 01673 PCVR pcvr; 01674 int ccvr; 01675 TL tlpwnd; 01676 01677 /* 01678 * Send all the messages that need to be sent... 01679 */ 01680 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 01681 01682 if (pcvr->pos.hwnd == NULL) 01683 continue; 01684 01685 /* 01686 * If the window's state didn't change, don't send the message. 01687 */ 01688 if ((pcvr->pos.flags & SWP_CHANGEMASK) == SWP_NOCHANGE) 01689 continue; 01690 01691 if ((pwnd = RevalidateHwnd(pcvr->pos.hwnd)) == NULL) { 01692 RIPMSG0(RIP_WARNING, "xxxSendChangedMsgs: window went away in middle"); 01693 pcvr->pos.flags = SWP_NOREDRAW | SWP_NOCHANGE; 01694 pcvr->pos.hwnd = NULL; 01695 continue; 01696 } 01697 01698 if (!IsStillWindowC(pcvr->pos.hwndInsertAfter)) { 01699 pcvr->pos.hwnd = NULL; 01700 continue; 01701 } 01702 01703 /* 01704 * Send the WM_WINDOWPOSCHANGED message... 01705 * 01706 * Make a frame copy of the WINDOWPOS, because the pcvr 01707 * info may get reused if SetWindowPos() 01708 * is called by the message handler: see the comments in 01709 * AllocSmwp(). 01710 * 01711 * WM_SIZE, WM_MOVE and WM_SHOW messages are sent by the 01712 * DefWindowProc() WM_WINDOWPOSCHANGED message processing. 01713 * 01714 * Note: It's okay to destroy the window while processing this 01715 * message, since this is the last call made by the window manager 01716 * with the window handle before returning from SetWindowPos(). 01717 * This also means we don't have to revalidate the pwnd. 01718 */ 01719 ThreadLockAlways(pwnd, &tlpwnd); 01720 xxxSendMessage(pwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pcvr->pos); 01721 01722 /* 01723 * Only send a shape change when moving/sizing/minimizing/restoring/ 01724 * maximizing (or framechange for NetMeeting to detect SetWindowRgn) 01725 */ 01726 if (FWINABLE() && 01727 (!(pcvr->pos.flags & SWP_NOCLIENTMOVE) || 01728 !(pcvr->pos.flags & SWP_NOCLIENTSIZE) || 01729 (pcvr->pos.flags & SWP_STATECHANGE) || 01730 (pcvr->pos.flags & SWP_FRAMECHANGED))) { 01731 xxxWindowEvent(EVENT_OBJECT_LOCATIONCHANGE, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, WEF_USEPWNDTHREAD); 01732 } 01733 ThreadUnlock(&tlpwnd); 01734 } // for (... pcvr ...) 01735 01736 01737 }

BOOL xxxSetWindowPos PWND  pwnd,
PWND  pwndInsertAfter,
int  x,
int  y,
int  cx,
int  cy,
UINT  flags
 

Definition at line 1468 of file swp.c.

References _DeferWindowPos(), BOOL, CheckLock, tagDISPLAYINFO::cMonitors, cy, FALSE, FixBogusSWP(), gpDispInfo, InternalBeginDeferWindowPos(), IsRectEmpty(), LOBYTE, NULL, tagWND::rcWindow, tagWND::spwndOwner, TestWF, TRUE, WFBORDERMASK, WFCAPTION, WFCHILD, WFVISIBLE, WFWIN31COMPAT, WFWIN50COMPAT, xxxEndDeferWindowPosEx(), and xxxRedrawWindow().

Referenced by CheckOnTop(), NtUserSetWindowPos(), ResetSharedDesktops(), xxxActivateThisWindow(), xxxCreateDesktop(), xxxCreateTooltip(), xxxDesktopThread(), xxxDestroyWindow(), xxxDrawDragRect(), xxxDWP_SetCursor(), xxxKeyEvent(), xxxMenuWindowProc(), xxxMetricsRecalc(), xxxMNOpenHierarchy(), xxxMNUpdateShownMenu(), xxxMoveWindow(), xxxMS_TrackMove(), xxxNextWindow(), xxxOldNextWindow(), xxxProcessEventMessage(), xxxRedrawFrame(), xxxRedrawFrameAndHook(), xxxResetTooltip(), xxxSetForegroundWindow2(), xxxSetInternalWindowPos(), xxxSetParent(), xxxSetShellWindow(), xxxSetWindowPlacement(), xxxShowSwitchWindow(), xxxShowTooltip(), xxxShowWindow(), xxxSwitchDesktop(), xxxSwitchToThisWindow(), xxxSwitchWndProc(), xxxSysCommand(), and xxxTrackPopupMenuEx().

01476 { 01477 PSMWP psmwp; 01478 BOOL fInval = FALSE; 01479 01480 #if DBG 01481 CheckLock(pwnd); 01482 01483 switch((ULONG_PTR)pwndInsertAfter) { 01484 case 0x0000FFFF: 01485 case (ULONG_PTR)HWND_TOPMOST: 01486 case (ULONG_PTR)HWND_NOTOPMOST: 01487 case (ULONG_PTR)HWND_TOP: 01488 case (ULONG_PTR)HWND_BOTTOM: 01489 break; 01490 01491 default: 01492 CheckLock(pwndInsertAfter); 01493 break; 01494 } 01495 #endif 01496 01497 /* 01498 * BACKWARD COMPATIBILITY HACKS 01499 * 01500 * Hack 1: For Win 3.0 and below, SetWindowPos() must ignore the 01501 * move and size flags if SWP_SHOWWINDOW or SWP_HIDEWINDOW 01502 * is specified. KnowledgePro is one application that depends on 01503 * this behavior for the positioning of its MDI icons. 01504 * 01505 * Hack 2: In 3.0, if SetWindowPos() is called with SWP_SHOWWINDOW 01506 * and the window is already visible, then the window was 01507 * completely invalidated anyway. So, we do that here too. 01508 * 01509 * NOTE: The placement of the invalidation AFTER the EndDeferWindowPos() 01510 * call means that if the guy is Z-ordering and showing a 3.0 window, 01511 * it may flash, because EndDefer calls DoSyncPaint, and we invalidate 01512 * again after that. Could be fixed with some major hackery in EndDefer, 01513 * and it's probably not worth the trouble. 01514 */ 01515 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) { 01516 01517 if (!TestWF(pwnd, WFWIN31COMPAT)) { 01518 01519 flags |= SWP_NOMOVE | SWP_NOSIZE; 01520 if ((flags & SWP_SHOWWINDOW) && TestWF(pwnd, WFVISIBLE)) 01521 fInval = TRUE; 01522 } 01523 } 01524 01525 /* 01526 * MULTIMONITOR HACKS 01527 * 01528 * if a app is centering or cliping a hidden owned window 01529 * to the primary monitor we should center the window to the owner 01530 * 01531 * this makes apps that center/position their own dialogs 01532 * work when the app is on a secondary monitor. 01533 */ 01534 if ( !TestWF(pwnd, WFWIN50COMPAT) && 01535 gpDispInfo->cMonitors > 1 && 01536 !(flags & SWP_NOMOVE) && 01537 !TestWF(pwnd, WFCHILD) && 01538 !TestWF(pwnd, WFVISIBLE) && 01539 (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION)) && 01540 pwnd->spwndOwner && 01541 TestWF(pwnd->spwndOwner, WFVISIBLE) && 01542 !IsRectEmpty(&pwnd->spwndOwner->rcWindow)) { 01543 01544 FixBogusSWP(pwnd, &x, &y, cx, cy, flags); 01545 01546 } 01547 01548 if (!(psmwp = InternalBeginDeferWindowPos(1)) || 01549 !(psmwp = _DeferWindowPos(psmwp, 01550 pwnd, 01551 pwndInsertAfter, 01552 x, 01553 y, 01554 cx, 01555 cy, 01556 flags))) { 01557 01558 return FALSE; 01559 } 01560 01561 01562 if (xxxEndDeferWindowPosEx(psmwp, flags & SWP_ASYNCWINDOWPOS)) { 01563 01564 if (fInval) { 01565 xxxRedrawWindow( 01566 pwnd, 01567 NULL, 01568 NULL, 01569 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); 01570 } 01571 01572 return TRUE; 01573 } 01574 01575 return FALSE; 01576 }

BOOL xxxSetWindowRgn PWND  pwnd,
HRGN  hrgn,
BOOL  fRedraw
 

Definition at line 5661 of file swp.c.

References _DeferWindowPos(), tagSMWP::acvr, BOOL, FALSE, HRGN_FULL, tagCVR::hrgnClip, InternalBeginDeferWindowPos(), NULL, PWND_TOP, SWR_FLAGS_NOREDRAW, SWR_FLAGS_REDRAW, UserValidateCopyRgn(), and xxxEndDeferWindowPosEx().

Referenced by NtUserSetWindowRgn().

05665 { 05666 PSMWP psmwp; 05667 HRGN hrgnClip = NULL; 05668 BOOL bRet = FALSE; 05669 05670 /* 05671 * Validate the region handle. We did this for 3.51, so 05672 * we better do it for later versions. Our validation will 05673 * make a copy of the clip-rgn and send it through to the 05674 * SetWIndowRgn code. Once this is set in the kernel, we 05675 * will return to the client and the old region will be deleted 05676 * there. 05677 * 05678 * If the region passed in is NULL, then we get rid of the 05679 * current retion. Map it to HRGN_FULL so that SetWindowPos() 05680 * can tell this is what the caller wants. 05681 */ 05682 if (hrgn) { 05683 05684 if ((hrgnClip = UserValidateCopyRgn(hrgn)) == NULL) { 05685 05686 #if DBG 05687 RIPMSG0(RIP_WARNING, "xxxSetWindowRgn: Failed to create region!"); 05688 #endif 05689 goto swrClean; 05690 } 05691 #ifdef USE_MIRRORING 05692 MirrorRegion(pwnd, hrgnClip, FALSE); 05693 #endif 05694 } else { 05695 05696 hrgnClip = HRGN_FULL; 05697 } 05698 05699 /* 05700 * Get a psmwp, and put the region in it, correctly offset. 05701 * Use SWP_FRAMECHANGED with acts really as a "empty" SetWindowPos 05702 * that still sends WM_WINDOWPOSCHANGING and CHANGED messages. 05703 * SWP_NOCHANGE ensures that we don't size, move, activate, zorder. 05704 */ 05705 if (psmwp = InternalBeginDeferWindowPos(1)) { 05706 05707 /* 05708 * psmwp gets freed automatically if this routine fails. 05709 */ 05710 if (psmwp = _DeferWindowPos( 05711 psmwp, 05712 pwnd, 05713 PWND_TOP, 05714 0, 05715 0, 05716 0, 05717 0, 05718 fRedraw ? SWR_FLAGS_REDRAW : SWR_FLAGS_NOREDRAW)) { 05719 05720 /* 05721 * Do the operation. Note that hrgn is still in window coordinates. 05722 * SetWindowPos() will change it to screen coordinates before 05723 * selecting into the window. 05724 */ 05725 psmwp->acvr[0].hrgnClip = hrgnClip; 05726 bRet = xxxEndDeferWindowPosEx(psmwp, FALSE); 05727 } 05728 } 05729 05730 /* 05731 * If the call failed, then delete our region we created. A FALSE 05732 * return means it should've never made it to the xxxSelectWindowRgn 05733 * call, so everything should be as it was. 05734 */ 05735 if (!bRet && (hrgnClip != HRGN_FULL)) { 05736 05737 swrClean: 05738 05739 GreDeleteObject(hrgnClip); 05740 } 05741 05742 return bRet; 05743 }

BOOL xxxSwpActivate PWND  pwndNewActive  ) 
 

Definition at line 1586 of file swp.c.

References AW_USE, BOOL, CheckLock, FALSE, GETPTI, gpqForeground, L, NULL, tagTHREADINFO::pq, PtiCurrent, SetWF, tagQ::spwndActive, tagQ::spwndActivePrev, TestwndChild, TIF_ALLOWFOREGROUNDACTIVATE, tagTHREADINFO::TIF_flags, TRUE, WFNONCPAINT, xxxActivateWindow(), and xxxSendMessage().

Referenced by xxxEndDeferWindowPosEx().

01588 { 01589 PTHREADINFO pti; 01590 01591 CheckLock(pwndNewActive); 01592 01593 if (pwndNewActive == NULL) 01594 return FALSE; 01595 01596 pti = PtiCurrent(); 01597 01598 if (TestwndChild(pwndNewActive)) { 01599 01600 xxxSendMessage(pwndNewActive, WM_CHILDACTIVATE, 0, 0L); 01601 01602 } else if (pti->pq->spwndActive != pwndNewActive) { 01603 01604 /* 01605 * Remember if this window wants to be active. We are either setting 01606 * our own window active (most likely), or setting a window of 01607 * another thread active on purpose. If so that means this thread is 01608 * controlling this window and will probably want to set itself 01609 * active and foreground really soon (for example, a setup 01610 * program doing dde to progman). Allow this thread and the target 01611 * thread to do forground activates. 01612 * 01613 * Let's stop doing this for NT5 in an effort to close the number 01614 * of ways applications can force a foreground change. This is not 01615 * quite needed anyway, because: 01616 * -If the current thread is already in the foreground, then it doesn't need 01617 * the TIF_ALLOWFOREGROUNDACTIVATE to make a foreground change. 01618 * -Since FRemoveForegroundActive removes this bit, the current thread 01619 * will lose it anyway during the xxxActivateWindow call. 01620 * -But xxxActivateWindow will set it back anyway because we're activating 01621 * a window from a different queue. 01622 * -The destination window/thread will take the foreground 01623 * as a result of the xxxActivateWindow call, hence it doesn't 01624 * need the bit on (if you're in the foreground, you don't need it). 01625 */ 01626 #ifdef DONTDOTHISANYMORE 01627 if ((pti->pq == gpqForeground) && (pti != GETPTI(pwndNewActive))) { 01628 /* 01629 * Allow foreground activate on the source and dest. 01630 */ 01631 pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 01632 TAGMSG1(DBGTAG_FOREGROUND, "xxxSwpActivate set TIF %#p", pti); 01633 GETPTI(pwndNewActive)->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 01634 TAGMSG1(DBGTAG_FOREGROUND, "xxxSwpActivate set TIF %#p", GETPTI(pwndNewActive)); 01635 } 01636 #endif 01637 01638 if (!xxxActivateWindow(pwndNewActive, AW_USE)) 01639 return FALSE; 01640 01641 /* 01642 * HACK ALERT: We set these bits to prevent 01643 * the frames from redrawing themselves in 01644 * the later call to DoSyncPaint(). 01645 * 01646 * Prevent these captions from being repainted during 01647 * the DoSyncPaint(). (bobgu 6/10/87) 01648 */ 01649 if (pti->pq->spwndActive != NULL) 01650 SetWF(pti->pq->spwndActive, WFNONCPAINT); 01651 01652 if (pti->pq->spwndActivePrev != NULL) 01653 SetWF(pti->pq->spwndActivePrev, WFNONCPAINT); 01654 01655 return TRUE; // Indicate that we diddled these bits 01656 } 01657 01658 return FALSE; 01659 }

PSMWP ZOrderByOwner PSMWP  psmwp  ) 
 

Definition at line 4613 of file swp.c.

References tagSMWP::acvr, tagSMWP::ccvr, CheckTopmost(), CTM_NOCHANGE, CTM_NOTOPMOST, CTM_TOPMOST, FindValidWindowPos(), GetRealOwner(), tagCVR::hrgnClip, NextOwnedWindow(), NULL, tagCVR::pos, ppos, tagCVR::pti, PW, SetTopmost(), tagWND::spwndParent, TrackZorder(), and ZOrderByOwner2().

Referenced by xxxEndDeferWindowPosEx().

04615 { 04616 int i; 04617 PWND pwnd; 04618 PWND pwndT; 04619 WINDOWPOS pos; 04620 PTHREADINFO ptiT; 04621 HRGN hrgnClipSave; 04622 04623 /* 04624 * Some of the windows in the SMWP list may be NULL at ths point 04625 * (removed because they'll be handled by their creator's thread) 04626 * so we've got to look for the first non-NULL window before we can 04627 * execute some of the tests below. FindValidWindowPos returns NULL if 04628 * the list has no valid windows in it. 04629 */ 04630 if (FindValidWindowPos(psmwp) == NULL) 04631 return psmwp; 04632 04633 /* 04634 * For each SWP in the array, move it to the end of the array 04635 * and generate its entire owner tree in sorted order. 04636 */ 04637 for (i = psmwp->ccvr; i-- != 0; ) { 04638 04639 int iScan; 04640 int iTop; 04641 int code; 04642 WINDOWPOS *ppos; 04643 HWND hwndTopmost; 04644 HWND hwndRegular; 04645 04646 if (psmwp->acvr[0].pos.hwnd == NULL) 04647 continue; 04648 04649 code = CheckTopmost(&psmwp->acvr[0].pos); 04650 04651 /* 04652 * Make a local copy for later... 04653 * 04654 * Why don't we copy all CVR fields? This seems pretty hard to maintain. 04655 * Perhaps because most of them haven't been used yet.... 04656 * 04657 */ 04658 pos = psmwp->acvr[0].pos; 04659 ptiT = psmwp->acvr[0].pti; 04660 hrgnClipSave = psmwp->acvr[0].hrgnClip; 04661 04662 /* 04663 * Move the CVR to the end (if it isn't already) 04664 */ 04665 iTop = psmwp->ccvr - 1; 04666 04667 if (iTop != 0) { 04668 04669 RtlCopyMemory(&psmwp->acvr[0], 04670 &psmwp->acvr[1], 04671 iTop * sizeof(CVR)); 04672 04673 psmwp->acvr[iTop].pos = pos; 04674 psmwp->acvr[iTop].pti = ptiT; 04675 psmwp->acvr[iTop].hrgnClip = hrgnClipSave; 04676 } 04677 04678 if ((psmwp = ZOrderByOwner2(psmwp, iTop)) == NULL) 04679 break; 04680 04681 /* 04682 * Deal with WEFTOPMOST bits. If we're SETTING the TOPMOST bits, 04683 * we want to set them for this window and 04684 * all its owned windows -- the owners stay unchanged. If we're 04685 * CLEARING, though, we need to enumerate ALL the windows, since 04686 * they all need to lose the topmost bit when one loses it. 04687 * 04688 * Note that since a status change doesn't necessarily mean that 04689 * the true Z order of the windows have changed, so ZOrderByOwner2 04690 * may not have enumerated all of the owned and owner windows. 04691 * So, we enumerate them separately here. 04692 */ 04693 if (code != CTM_NOCHANGE) { 04694 PWND pwndRoot = PW(pos.hwnd); 04695 #if DBG 04696 PWND pwndOriginal = pwndRoot; 04697 #endif 04698 04699 /* 04700 * Make sure we're z-ordering this window. Or settting topmost 04701 * is bad. 04702 */ 04703 UserAssert(!(pos.flags & SWP_NOZORDER)); 04704 04705 /* 04706 * If we're CLEARING the topmost, then we want to enumerate 04707 * the owners and ownees, so start our enumeration at the root. 04708 */ 04709 if (code == CTM_NOTOPMOST) { 04710 04711 while (pwnd = GetRealOwner(pwndRoot)) 04712 pwndRoot = pwnd; 04713 } 04714 04715 #if DBG 04716 if ((pos.flags & SWP_NOOWNERZORDER) 04717 && ((pwndOriginal != pwndRoot) 04718 || (NextOwnedWindow(NULL, pwndRoot, pwndRoot->spwndParent) != NULL))) { 04719 /* 04720 * We're not doing owner z-order but pwndOriginal has an owner and/or 04721 * owns some windows. The problem is, SetTopMost always affects the whole 04722 * owner/ownee group. So we might end up with WFTOGGLETOPMOST windows 04723 * that won't be z-ordered. It has always been like that. 04724 */ 04725 RIPMSG2(RIP_WARNING, "ZOrderByOwner: Topmost change while using SWP_NOOWNERZORDER." 04726 " pwndRoot:%p pwndOriginal:%p", 04727 pwndRoot, pwndOriginal); 04728 } 04729 #endif 04730 04731 SetTopmost(pwndRoot, code == CTM_TOPMOST); 04732 } 04733 04734 /* 04735 * Now scan the list forwards (from the bottom of the 04736 * owner tree towards the root) looking for the window 04737 * we were positioning originally (it may have been in 04738 * the middle of the owner tree somewhere). Update the 04739 * window pos structure stored there with the original 04740 * information (though the z-order info is retained from 04741 * the sort). 04742 */ 04743 pwnd = NULL; 04744 hwndTopmost = hwndRegular = NULL; 04745 for (iScan = iTop; iScan != psmwp->ccvr; iScan++) { 04746 04747 ppos = &psmwp->acvr[iScan].pos; 04748 04749 if (ppos->hwnd == pos.hwnd) { 04750 ppos->x = pos.x; 04751 ppos->y = pos.y; 04752 ppos->cx = pos.cx; 04753 ppos->cy = pos.cy; 04754 ppos->flags ^= ((ppos->flags ^ pos.flags) & ~SWP_NOZORDER); 04755 psmwp->acvr[iScan].hrgnClip = hrgnClipSave; 04756 } 04757 04758 pwndT = pwnd; 04759 pwnd = TrackZorder(ppos, pwndT, &hwndTopmost, &hwndRegular); 04760 } 04761 } 04762 04763 return psmwp; 04764 }

PSMWP ZOrderByOwner2 PSMWP  psmwp,
int  iTop
 

Definition at line 4323 of file swp.c.

References tagSMWP::acvr, AddSelfAndOwnees(), BOOL, tagSMWP::ccvr, GetRealOwner(), HW, IsOwnee(), NextOwnedWindow(), NULL, tagCVR::pos, ppos, PW, PWInsertAfter(), tagWND::spwndOwner, tagWND::spwndParent, TestWF, and WFBOTTOMMOST.

Referenced by ZOrderByOwner().

04326 { 04327 PWND pwndT; 04328 PWND pwndOwnerRoot; 04329 PWND pwndTopInsert; 04330 PWINDOWPOS ppos; 04331 PWND pwnd; 04332 PWND pwndInsertAfter; 04333 BOOL fHasOwnees; 04334 04335 ppos = &psmwp->acvr[iTop].pos; 04336 04337 /* 04338 * If inside message box processing, not Z ordering, 04339 * or if SWP_NOOWNERZORDER specified, all done. 04340 */ 04341 // LATER 04-Mar-1992 MikeKe 04342 // do we have a substitue for fMessageBox 04343 if ((ppos->flags & SWP_NOZORDER) || 04344 (ppos->flags & SWP_NOOWNERZORDER)) { 04345 04346 return psmwp; 04347 } 04348 04349 pwnd = PW(ppos->hwnd); 04350 pwndInsertAfter = PWInsertAfter(ppos->hwndInsertAfter); 04351 04352 fHasOwnees = (NextOwnedWindow(NULL, pwnd, pwnd->spwndParent) != NULL); 04353 04354 /* 04355 * If the window isn't owned, and it doesn't own any other window, 04356 * do nothing. 04357 */ 04358 if (!pwnd->spwndOwner && !fHasOwnees) 04359 return psmwp; 04360 04361 /* 04362 * Find the unowned window to start building the tree from. 04363 * This is easy: just zip upwards until we find a window with no owner. 04364 */ 04365 pwndOwnerRoot = pwndT = pwnd; 04366 while ((pwndT = GetRealOwner(pwndT)) != NULL) 04367 pwndOwnerRoot = pwndT; 04368 04369 /* 04370 * We need to calculate what pwndInsertAfter should be for 04371 * the first (topmost) window of the SWP list. 04372 * 04373 * If pwndInsertAfter is part of the owner tree we'll be building, 04374 * then we want to reorder windows within the owner group, so the 04375 * entire group should maintain it's relative order. 04376 * 04377 * If pwndInsertAfter is part of another owner tree, then we want 04378 * the whole group relative to that. 04379 * 04380 * If pwndInsertAfter is HWND_BOTTOM, then we want the whole 04381 * group to go to the bottom, so we position it relative to 04382 * the bottom most window that is not part of the tree. We also 04383 * want to put pwnd on the bottom relative to its owner siblings. 04384 * 04385 * If pwndInsertAfter is HWND_TOP, then bring the whole group 04386 * to the top, as well as bringing pwnd to the top relative to its 04387 * owner siblings. 04388 * 04389 * Assume the topmost of group is same as topmost 04390 * (true for all cases except where rearranging subtree of group) 04391 */ 04392 pwndTopInsert = pwndInsertAfter; 04393 if (pwndInsertAfter == (PWND)HWND_TOP) { 04394 04395 /* 04396 * Bring the whole group to the top: nothing fancy to do. 04397 */ 04398 04399 } else if (pwndInsertAfter == (PWND)HWND_BOTTOM) { 04400 04401 /* 04402 * Put the whole group on the bottom. pwndTopInsert should 04403 * be the bottommost window unowned by pwndOwnerRoot. 04404 */ 04405 for (pwndT = pwnd->spwndParent->spwndChild; 04406 (pwndT != NULL) && !TestWF(pwndT, WFBOTTOMMOST); pwndT = pwndT->spwndNext) { 04407 04408 /* 04409 * If it's not owned, then this is the bottommost so far. 04410 */ 04411 if (!IsOwnee(pwndT, pwndOwnerRoot)) 04412 pwndTopInsert = pwndT; 04413 } 04414 04415 /* 04416 * If there were no other windows not in our tree, 04417 * then there is no Z ordering change to be done. 04418 */ 04419 if (pwndTopInsert == (PWND)HWND_BOTTOM) 04420 ppos->flags |= SWP_NOZORDER; 04421 04422 } else { 04423 04424 /* 04425 * pwndInsertAfter is a window. Compute pwndTopInsert 04426 */ 04427 if (IsOwnee(pwndInsertAfter, pwndOwnerRoot)) { 04428 04429 /* 04430 * SPECIAL CASE: If we do not own any windows, and we're 04431 * being moved within our owner group in such a way that 04432 * we remain above our owner, then no other windows will 04433 * be moving with us, and we can just exit 04434 * without building our tree. This can save a LOT of 04435 * extra work, especially with the MS apps CBT tutorials, 04436 * which do this kind of thing a lot. 04437 */ 04438 if (!fHasOwnees) { 04439 04440 /* 04441 * Make sure we will still be above our owner by searching 04442 * for our owner starting from pwndInsertAfter. If we 04443 * find our owner, then pwndInsertAfter is above it. 04444 */ 04445 for (pwndT = pwndInsertAfter; pwndT != NULL; 04446 pwndT = pwndT->spwndNext) { 04447 04448 if (pwndT == pwnd->spwndOwner) 04449 return psmwp; 04450 } 04451 } 04452 04453 /* 04454 * Part of same group: Find out which window the topmost 04455 * of the group is currently inserted behind. 04456 */ 04457 pwndTopInsert = (PWND)HWND_TOP; 04458 for (pwndT = pwnd->spwndParent->spwndChild; pwndT != NULL; 04459 pwndT = pwndT->spwndNext) { 04460 04461 if (IsOwnee(pwndT, pwndOwnerRoot)) 04462 break; 04463 04464 pwndTopInsert = pwndT; 04465 } 04466 } 04467 } 04468 04469 /* 04470 * Okay, now go recursively build the owned window list... 04471 */ 04472 if (!(ppos->flags & SWP_NOZORDER)) { 04473 04474 /* 04475 * First "delete" the last entry (the one we're sorting with) 04476 */ 04477 psmwp->ccvr--; 04478 04479 psmwp = AddSelfAndOwnees(psmwp, 04480 pwndOwnerRoot, 04481 pwnd, 04482 pwndInsertAfter, 04483 iTop); 04484 04485 /* 04486 * Now set the place where the whole group is going. 04487 */ 04488 if (psmwp != NULL) 04489 psmwp->acvr[iTop].pos.hwndInsertAfter = HW(pwndTopInsert); 04490 } 04491 04492 return psmwp; 04493 }

BOOL zzzBltValidBits PSMWP  psmwp  ) 
 

Definition at line 2681 of file swp.c.

References _GetProp(), tagSMWP::acvr, AnySpbs, BEGINATOMICCHECK, BltValidInit(), BOOL, tagSMWP::ccvr, CombineOldNewVis(), CopyRgn, DeferWinEventNotify, dwFlags, DWORD, tagCVR::dxBlt, tagCVR::dyBlt, ENDATOMICCHECK, FALSE, FindSpb(), FLayeredOrRedirected(), FreeSpb(), tagCVR::fsRE, gcountPWO, ghrgnInvalid, ghrgnInvalidSum, ghrgnSWP1, ghrgnValid, ghrgnValidSum, ghrgnVisNew, gpDispInfo, tagDISPLAYINFO::hdcScreen, tagDISPLAYINFO::hDev, HRGN_FULL, tagCVR::hrgnInterMonitor, tagWND::hrgnUpdate, tagCVR::hrgnVisOld, IDC_CHILDRENONLY, IDC_CLIENTONLY, IDC_MOVEBLT, IntersectRgn, IsStillWindowC(), NULL, tagCVR::pos, ppos, PROP_LAYER, PW, PWNDDESKTOP, tagCVR::rcBlt, tagWND::rcWindow, RE_INVALID, RE_INVALIDSUM, RE_VALID, RE_VALIDSUM, RE_VISNEW, RE_VISOLD, RestoreSpb(), RevalidateHwnd, RSPB_INVALIDATE_SSB, RSPB_NO_INVALIDATE, SetRectRgnIndirect(), SpbCheck(), SpbCheckRect(), tagWND::spwndParent, SubtractRgn, SwpCalcVisRgn(), TestWF, TRUE, UINT, UnionRgn, WFCLIPCHILDREN, WFHASSPB, WFWIN31COMPAT, xxxInternalInvalidate(), zzzChangeStates(), zzzEndDeferWinEventNotify, and zzzInvalidateDCCache().

Referenced by xxxEndDeferWindowPosEx().

02683 { 02684 int ccvr; 02685 int cIter; 02686 PCVR pcvr; 02687 PWND pwnd; 02688 PWND pwndParent; 02689 PWND pwndT; 02690 PWINDOWPOS ppos; 02691 HRGN hrgnInvalidate; 02692 UINT fsRgnEmpty; 02693 UINT fsSumEmpty; 02694 int cwndShowing; 02695 BOOL fSyncPaint = FALSE; 02696 BOOL fInvalidateLayers = FALSE; 02697 HDC hdcScreen = NULL; 02698 02699 DeferWinEventNotify(); 02700 GreLockDisplay(gpDispInfo->hDev); 02701 02702 /* 02703 * Compute old visrgns and count total CVRs in list. A side-effect of 02704 * BltValidInit is that revalidates all the windows in the SMWP array. 02705 */ 02706 02707 02708 if ((cIter = BltValidInit(psmwp)) == 0) { 02709 02710 CleanupAndExit: 02711 02712 /* 02713 * Go through the cvr list and free the regions that BltValidInit() 02714 * created. 02715 */ 02716 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 02717 02718 if (pcvr->hrgnVisOld) { 02719 GreDeleteObject(pcvr->hrgnVisOld); 02720 pcvr->hrgnVisOld = NULL; 02721 } 02722 } 02723 02724 goto UnlockAndExit; 02725 } 02726 02727 /* 02728 * We left the crit sect since last time we validated the smwp. Validate 02729 * it again, and find the first WINDOWPOS structure with a non-NULL 02730 * hwnd in it. 02731 */ 02732 ppos = NULL; 02733 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 02734 02735 /* 02736 * Revalidate window and if it's invalid, NULL it out in the WINDOWPOS 02737 * struct. 02738 */ 02739 pwnd = RevalidateHwnd(pcvr->pos.hwnd); 02740 02741 if ((pwnd == NULL) || 02742 (pwnd->spwndParent == NULL) || 02743 !IsStillWindowC(pcvr->pos.hwndInsertAfter)) { 02744 02745 pcvr->pos.hwnd = NULL; 02746 pcvr->pos.flags = SWP_NOREDRAW | SWP_NOCHANGE; 02747 continue; 02748 } 02749 02750 /* 02751 * Remember the first WINDOWPOS structure that has a non-NULL 02752 * hwnd. 02753 */ 02754 if (ppos == NULL) 02755 ppos = &pcvr->pos; 02756 } 02757 02758 if (ppos == NULL) 02759 goto CleanupAndExit; 02760 02761 UserAssert(PW(ppos->hwnd)); 02762 pwndParent = PW(ppos->hwnd)->spwndParent; 02763 UserAssert(pwndParent); 02764 02765 /* 02766 * Go account for any dirty DCs at this point, to ensure that: 02767 * - any drawing done before we create an SPB will not 02768 * later invalidate that SPB 02769 * - the SPB regions reflect the true state of the screen, 02770 * so that we don't validate parts of windows that are dirty. 02771 * 02772 * We must make this call before we change any window state. 02773 */ 02774 if (AnySpbs()) 02775 SpbCheck(); 02776 02777 /* 02778 * Change the window states 02779 */ 02780 zzzChangeStates(pwndParent, psmwp); 02781 02782 /* 02783 * move window bits around 02784 * 02785 * Invalidate the DCs for the siblings of this window. 02786 * 02787 * If our parent is not clipchildren, then we don't need to 02788 * invalidate its DCs. If it IS clipchildren, its client visrgn 02789 * will be changing, so we must invalidate it too. 02790 * 02791 * Note, because IDC_MOVEBLT is set, final completion of WNDOBJ 02792 * notification is delayed until GreClientRgnDone is called. 02793 * This final notification does not happen until after the 02794 * window move blts have completed. 02795 */ 02796 zzzInvalidateDCCache(pwndParent, 02797 IDC_MOVEBLT | 02798 (TestWF(pwndParent, WFCLIPCHILDREN) ? 02799 IDC_CLIENTONLY : IDC_CHILDRENONLY)); 02800 02801 /* 02802 * Now, do the bltting or whatever that is required. 02803 */ 02804 fsSumEmpty = RE_VALIDSUM | RE_INVALIDSUM; 02805 hrgnInvalidate = ghrgnInvalidSum; 02806 02807 /* 02808 * Init count of windows being shown with SWP_SHOWWINDOW 02809 * for our backward compatibility hack later. 02810 */ 02811 cwndShowing = 0; 02812 02813 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 02814 02815 /* 02816 * Decrement loop count. When cIter is 0, then 02817 * we're on the last pass through the loop. 02818 */ 02819 cIter--; 02820 02821 if (pcvr->pos.hwnd == NULL) 02822 continue; 02823 02824 /* 02825 * If we're not redrawing, try the next one. 02826 */ 02827 if (pcvr->pos.flags & SWP_NOREDRAW) 02828 continue; 02829 02830 /* 02831 * Some drawing has been done 02832 */ 02833 fSyncPaint = TRUE; 02834 02835 pwnd = PW(pcvr->pos.hwnd); 02836 02837 fsRgnEmpty = pcvr->fsRE; 02838 02839 /* 02840 * Sprites should not be invalidated or cause invalidation. 02841 */ 02842 if (FLayeredOrRedirected(pwnd)) { 02843 if (_GetProp(pwnd, PROP_LAYER, TRUE) == NULL) 02844 goto InvalidEmpty; 02845 02846 /* 02847 * Sizing or showing uncovers new bits for a window, so 02848 * do the normal invalidation in this case. When sizing makes a 02849 * window smaller setting fInvalidateLayers to TRUE has the side 02850 * effect of allowing other layered windows to be invalidated. 02851 * Ideally, it should only allow invlalidating just the windows 02852 * that resized or showed. This would be a bunch of work, but we 02853 * should consider it for later. 02854 */ 02855 if ((pcvr->pos.flags & SWP_NOSIZE) && 02856 !(pcvr->pos.flags & SWP_SHOWWINDOW)) { 02857 goto InvalidEmpty; 02858 } else { 02859 fInvalidateLayers = TRUE; 02860 } 02861 } 02862 02863 /* 02864 * Calculate the new visrgn 02865 */ 02866 if (!SwpCalcVisRgn(pwnd, ghrgnVisNew)) 02867 fsRgnEmpty |= RE_VISNEW; 02868 02869 /* 02870 * If the window is obscured by another window with an SPB, 02871 * we have to ensure that that SPB gets invalidated properly 02872 * since the app may not be getting a WM_PAINT msg or anything 02873 * to invalidate the bits. 02874 */ 02875 if (AnySpbs()) 02876 SpbCheckRect(pwnd, &pwnd->rcWindow, DCX_WINDOW); 02877 02878 /* 02879 * Calculate ghrgnValid: 02880 * 02881 * ghrgnValid = OffsetRgn(rcBlt, -dxBlt, -dyBlt) & hrgnVisOld 02882 * ghrgnValid = ghrgnValid - ghrgnValidSum 02883 * OffsetRgn(ghrgnValid, dxBlt, dyBlt); 02884 * ghrgnValid = ghrgnValid - hrgnUpdate 02885 * ghrgnValid = ghrgnValid & hrgnVisNew; 02886 * 02887 * If either the old or new visrgns are empty, there 02888 * can be no valid bits... 02889 */ 02890 if (fsRgnEmpty & (RE_VISOLD | RE_VISNEW)) 02891 goto ValidEmpty; 02892 02893 /* 02894 * If the entire window is already completely invalid, blow out. 02895 */ 02896 if (pwnd->hrgnUpdate == HRGN_FULL) 02897 goto ValidEmpty; 02898 02899 /* 02900 * If the blt rectangle is empty, there can be no valid bits. 02901 */ 02902 if ((pcvr->rcBlt.right <= pcvr->rcBlt.left) || 02903 (pcvr->rcBlt.bottom <= pcvr->rcBlt.top)) { 02904 02905 goto ValidEmpty; 02906 } 02907 02908 GreSetRectRgn(ghrgnSWP1, 02909 pcvr->rcBlt.left - pcvr->dxBlt, 02910 pcvr->rcBlt.top - pcvr->dyBlt, 02911 pcvr->rcBlt.right - pcvr->dxBlt, 02912 pcvr->rcBlt.bottom - pcvr->dyBlt); 02913 02914 switch (IntersectRgn(ghrgnValid, ghrgnSWP1, pcvr->hrgnVisOld)) { 02915 case NULLREGION: 02916 case ERROR: 02917 goto ValidEmpty; 02918 break; 02919 } 02920 02921 if (!(fsSumEmpty & RE_VALIDSUM)) { 02922 switch (SubtractRgn(ghrgnValid, ghrgnValid, ghrgnValidSum)) { 02923 case NULLREGION: 02924 case ERROR: 02925 goto ValidEmpty; 02926 break; 02927 } 02928 } 02929 02930 if ((pcvr->dxBlt | pcvr->dyBlt) != 0) 02931 GreOffsetRgn(ghrgnValid, pcvr->dxBlt, pcvr->dyBlt); 02932 02933 /* 02934 * Now subtract off the update regions of ourself and any 02935 * non-clipchildren parents... 02936 */ 02937 pwndT = pwnd; 02938 02939 do { 02940 02941 if (pwndT->hrgnUpdate == HRGN_FULL) 02942 goto ValidEmpty; 02943 02944 if (pwndT->hrgnUpdate != NULL) { 02945 switch (SubtractRgn(ghrgnValid, ghrgnValid, pwndT->hrgnUpdate)) { 02946 case NULLREGION: 02947 case ERROR: 02948 goto ValidEmpty; 02949 break; 02950 } 02951 } 02952 02953 pwndT = pwndT->spwndParent; 02954 02955 } while (pwndT && !TestWF(pwndT, WFCLIPCHILDREN)); 02956 02957 /* 02958 * Subtract out the intermonitor blt pieces. 02959 */ 02960 if (pcvr->hrgnInterMonitor != NULL) { 02961 switch (SubtractRgn(ghrgnValid, ghrgnValid, pcvr->hrgnInterMonitor)) { 02962 case NULLREGION: 02963 case ERROR: 02964 goto ValidEmpty; 02965 } 02966 } 02967 02968 switch (IntersectRgn(ghrgnValid, ghrgnValid, ghrgnVisNew)) { 02969 case NULLREGION: 02970 case ERROR: 02971 02972 ValidEmpty: 02973 02974 fsRgnEmpty |= RE_VALID; 02975 break; 02976 } 02977 02978 /* 02979 * Before we restore the restore bits over part of our 02980 * image, we need to first copy any valid bits to their 02981 * final destination. 02982 */ 02983 if (!(fsRgnEmpty & RE_VALID) && ((pcvr->dxBlt | pcvr->dyBlt) != 0)) { 02984 02985 if (hdcScreen == NULL) 02986 hdcScreen = gpDispInfo->hdcScreen; 02987 02988 GreSelectVisRgn(hdcScreen, ghrgnValid, SVR_COPYNEW); 02989 02990 #ifdef _WINDOWBLT_NOTIFICATION_ 02991 /* 02992 * Define _WINDOWBLT_NOTIFICATION_ to turn on Window BLT notification. 02993 * This notification will set a special flag in the SURFOBJ passed to 02994 * drivers when the DrvCopyBits operation is called to move a window. 02995 * 02996 * See also: 02997 * ntgdi\gre\maskblt.cxx 02998 */ 02999 NtGdiBitBlt(hdcScreen, 03000 pcvr->rcBlt.left, 03001 pcvr->rcBlt.top, 03002 pcvr->rcBlt.right - pcvr->rcBlt.left, 03003 pcvr->rcBlt.bottom - pcvr->rcBlt.top, 03004 hdcScreen, 03005 pcvr->rcBlt.left - pcvr->dxBlt, 03006 pcvr->rcBlt.top - pcvr->dyBlt, 03007 SRCCOPY, 03008 0, 03009 GBB_WINDOWBLT); 03010 #else 03011 GreBitBlt(hdcScreen, 03012 pcvr->rcBlt.left, 03013 pcvr->rcBlt.top, 03014 pcvr->rcBlt.right - pcvr->rcBlt.left, 03015 pcvr->rcBlt.bottom - pcvr->rcBlt.top, 03016 hdcScreen, 03017 pcvr->rcBlt.left - pcvr->dxBlt, 03018 pcvr->rcBlt.top - pcvr->dyBlt, 03019 SRCCOPY, 03020 0); 03021 #endif 03022 } 03023 03024 /* 03025 * Now take care of any SPB bit restoration we need to do. 03026 * 03027 * Calculate the region to clip the RestoreSpb() output to: 03028 * 03029 * ghrgnInvalid = hrgnVisOld - hrgnVisNew 03030 */ 03031 if (TestWF(pwnd, WFHASSPB) && 03032 !(fsRgnEmpty & RE_VISOLD) && 03033 CombineOldNewVis(ghrgnInvalid, pcvr->hrgnVisOld, ghrgnVisNew, RGN_DIFF, fsRgnEmpty)) { 03034 03035 UINT retRSPB; 03036 03037 /* 03038 * Perform SPB bits restore. We pass RestoreSpb() the region of 03039 * the part of the SPB that got uncovered by this window rearrangement. 03040 * It tries to restore as much of this area as it can from the SPB, 03041 * and returns the area that could not be restored from the SPB. 03042 * 03043 * The device driver's SaveBitmap() function does not clip at all 03044 * when it restores bits, which means that it might write bits 03045 * in an otherwise valid area. This means that the invalid area 03046 * returned by RestoreSpb() may actually be LARGER than the original 03047 * hrgnSpb passed in. 03048 * 03049 * RestoreSpb() returns TRUE if some part of ghrgnInvalid needs 03050 * to be invalidated. 03051 */ 03052 if ((retRSPB = RestoreSpb(pwnd, ghrgnInvalid, &hdcScreen)) == RSPB_NO_INVALIDATE) { 03053 03054 /* 03055 * If hrgnVisNew is empty, then we know the whole invalid 03056 * area is empty. 03057 */ 03058 if (fsRgnEmpty & RE_VISNEW) 03059 goto InvalidEmpty; 03060 03061 } else if (retRSPB == RSPB_INVALIDATE_SSB) { 03062 03063 /* 03064 * If RestoreSpb actually invalidated some area and we already 03065 * have a ghrgnValidSum then subtract the newly invalidated area 03066 * Warning this region subtract is not in the Win 3.1 code but 03067 * they probably did not have the problem as severe because their 03068 * drivers were limited to one level of SaveScreenBits 03069 */ 03070 if (!(fsSumEmpty & RE_VALIDSUM)) 03071 SubtractRgn(ghrgnValidSum, ghrgnValidSum, ghrgnInvalid); 03072 } 03073 03074 /* 03075 * ghrgnInvalid += hrgnVisNew 03076 */ 03077 if (!(fsRgnEmpty & RE_VISNEW)) 03078 UnionRgn(ghrgnInvalid, ghrgnInvalid, ghrgnVisNew); 03079 03080 /* 03081 * Some of the area we calculated as valid may have gotten 03082 * obliterated by the SPB restore. To ensure this isn't 03083 * the case, subtract off the ghrgnInvalid returned by RestoreSpb. 03084 */ 03085 // LATER mikeke VALIDSUM / ghrgnValid mismatch 03086 if (!(fsRgnEmpty & RE_VALIDSUM)) { 03087 switch (SubtractRgn(ghrgnValid, ghrgnValid, ghrgnInvalid)) { 03088 case NULLREGION: 03089 case ERROR: 03090 fsRgnEmpty |= RE_VALIDSUM; 03091 break; 03092 } 03093 } 03094 03095 } else { 03096 03097 /* 03098 * No SPB. Simple ghrgnInvalid calculation is: 03099 * 03100 * ghrgnInvalid = hrgnVisNew + hrgnVisOld; 03101 */ 03102 if (pcvr->hrgnVisOld == NULL) { 03103 03104 /* 03105 * If we couldn't create hrgnVisOld, then 03106 * invalidate the entire parent 03107 */ 03108 SetRectRgnIndirect(ghrgnInvalid, &pwndParent->rcWindow); 03109 } else { 03110 03111 if (!CombineOldNewVis(ghrgnInvalid, 03112 pcvr->hrgnVisOld, 03113 ghrgnVisNew, 03114 RGN_OR, 03115 fsRgnEmpty)) { 03116 03117 goto InvalidEmpty; 03118 } 03119 } 03120 } 03121 03122 /* 03123 * Update ghrgnValidSum 03124 * 03125 * ghrgnValidSum += ghrgnValid 03126 */ 03127 if (!(fsRgnEmpty & RE_VALID)) { 03128 03129 /* 03130 * If the sum region is empty, then COPY instead of OR 03131 */ 03132 if (fsSumEmpty & RE_VALIDSUM) 03133 CopyRgn(ghrgnValidSum, ghrgnValid); 03134 else 03135 UnionRgn(ghrgnValidSum, ghrgnValid, ghrgnValidSum); 03136 fsSumEmpty &= ~RE_VALIDSUM; 03137 } 03138 03139 /* 03140 * Subtract ghrgnValidSum from ghrgnInvalid if non-empty, 03141 * otherwise use ghrgnValid. Note, ghrgnValid has been OR'ed 03142 * into ghrgnValidSum already. 03143 */ 03144 if (!(fsSumEmpty & RE_VALIDSUM) || !(fsRgnEmpty & RE_VALID)) { 03145 switch (SubtractRgn(ghrgnInvalid, ghrgnInvalid, 03146 !(fsSumEmpty & RE_VALIDSUM) ? ghrgnValidSum : ghrgnValid)) { 03147 case NULLREGION: 03148 case ERROR: 03149 InvalidEmpty: 03150 fsRgnEmpty |= RE_INVALID; 03151 break; 03152 } 03153 } 03154 03155 /* 03156 * If there are any SPB bits left over, it wasn't just created 03157 * (SWP_SHOWWINDOW), and an operation occured that invalidates 03158 * the spb bits, get rid of the spb. A move, size, hide, or 03159 * zorder operation will invalidate the bits. Note that we do this 03160 * outside of the SWP_NOREDRAW case in case the guy set that flag 03161 * when he had some SPB bits lying around. 03162 */ 03163 if (TestWF(pwnd, WFHASSPB) && !(pcvr->pos.flags & SWP_SHOWWINDOW) && 03164 (pcvr->pos.flags & 03165 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW)) 03166 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) { 03167 03168 FreeSpb(FindSpb(pwnd)); 03169 } 03170 03171 /* 03172 * Finally, free up hrgnVisOld. 03173 */ 03174 if (pcvr->hrgnVisOld) { 03175 GreDeleteObject(pcvr->hrgnVisOld); 03176 pcvr->hrgnVisOld = NULL; 03177 } 03178 03179 /* 03180 * BACKWARD COMPATIBILITY HACK 03181 * 03182 * In 3.0, a ShowWindow() NEVER invalidated any of the children. 03183 * It would invalidate the parent and the window being shown, but 03184 * no others. 03185 * 03186 * We only apply hack (a) to 3.0 apps when all the windows involved 03187 * are doing a SWP_SHOWWINDOW: if any aren't, then we have to make 03188 * sure the siblings are invalidated too. So, we count the windows 03189 * doing a SHOWWINDOW and compare it to the total count in the CVR. 03190 */ 03191 if (!TestWF(pwnd, WFWIN31COMPAT) && (pcvr->pos.flags & SWP_SHOWWINDOW)) 03192 cwndShowing++; 03193 03194 /* 03195 * Update ghrgnInvalidSum: 03196 * 03197 * ghrgnInvalidSum += ghrgnInvalid 03198 */ 03199 if (!(fsRgnEmpty & RE_INVALID)) { 03200 03201 /* 03202 * BACKWARD COMPATIBILITY HACK 03203 * 03204 * In many cases including ShowWindow, CS_V/HREDRAW, 03205 * SWP_NOCOPYBITS, etc, 3.0 always invalidated the window with 03206 * (HRGN)1, regardless of how it was clipped by children, siblings, 03207 * or parents. Besides being more efficient, this caused child 03208 * windows that would otherwise not get update regions to get 03209 * invalidated -- see the hack notes in InternalInvalidate2. 03210 * 03211 * This is a performance hack (usually) because (HRGN)1 can save 03212 * a lot of region calculations in the normal case. So, we do this 03213 * for 3.1 apps as well as 3.0 apps. 03214 * 03215 * We detect the case as follows: invalid area not empty, 03216 * valid area empty, and new visrgn not empty. 03217 */ 03218 if ((fsRgnEmpty & RE_VALID) && !(fsRgnEmpty & RE_VISNEW)) { 03219 03220 /* 03221 * With the parameters we use InternalInvalidate() does 03222 * not leave the critical section 03223 */ 03224 BEGINATOMICCHECK(); 03225 xxxInternalInvalidate(pwnd, 03226 HRGN_FULL, 03227 RDW_INVALIDATE | 03228 RDW_FRAME | 03229 RDW_ERASE | 03230 RDW_ALLCHILDREN); 03231 ENDATOMICCHECK(); 03232 } 03233 03234 /* 03235 * If the sum region is empty, then COPY instead of OR 03236 */ 03237 if (fsSumEmpty & RE_INVALIDSUM) { 03238 03239 /* 03240 * HACK ALERT: 03241 * If this is the last pass through the loop (cIter == 0) 03242 * and ghrgnInvalidSum is currently empty, 03243 * then instead of copying ghrgnInvalid to ghrgnInvalidSum, 03244 * just set hrgnInvalidate to ghrgnInvalid. This saves 03245 * a region copy in the single-window case. 03246 */ 03247 if (cIter == 0) { 03248 hrgnInvalidate = ghrgnInvalid; 03249 } else { 03250 CopyRgn(ghrgnInvalidSum, ghrgnInvalid); 03251 } 03252 03253 } else { 03254 03255 UnionRgn(ghrgnInvalidSum, ghrgnInvalid, ghrgnInvalidSum); 03256 } 03257 03258 fsSumEmpty &= ~RE_INVALIDSUM; 03259 } 03260 } // for (... pcvr ...) 03261 03262 /* 03263 * Now, invalidate as needed. 03264 */ 03265 if (!(fsSumEmpty & RE_INVALIDSUM)) { 03266 03267 /* 03268 * BACKWARD COMPATIBILITY HACK (see above) 03269 * 03270 * If all the windows involved were being shown, then 03271 * invalidate the parent ONLY -- don't enumerate any children. 03272 * (the windows involved have already been invalidated above). 03273 * This hack is only applied to 3.0 apps (see above). 03274 */ 03275 03276 /* 03277 * More hack-o-rama. On Win3.1, the desktop paint would only 03278 * repaint those portions inside the rect returned from GetClipBox(). 03279 * Dialogs with spbs outside the rect returned from GetClipBox() would 03280 * not get their spbs invalidated until later, when you clicked on 03281 * them to make them active. The only dialog that wouldn't really loose 03282 * its bits is the control panel desktop dialog, which would restore 03283 * its bad bits when it went away (in certain configurations). On 03284 * NT, the desktop would repaint and then the dialog would go away. 03285 * On Win3.1, the dialog would go away and then the desktop would 03286 * repaint. On NT, because of preemption and little differences in 03287 * painting order between applications, there was an opportunity to 03288 * put bad bits on the screen, on Win3.1 there wasn't. 03289 * 03290 * Now... the below code that passes RDW_NOCHILDREN only gets executed 03291 * if the app is marked as a win3.0 app (latest CorelDraw, also wep 03292 * freecell demonstrates the same problem). This code would get 03293 * executed when a dialog got shown. So for a win3.0 app, spb would get 03294 * saved, the dialog would get shown, the desktop invalidated, the 03295 * desktop would paint, the spb would get clobbered. In short, when 03296 * a win3.0 app would put up a dialog, all spbs would get freed because 03297 * of the new (and correct) way the desktop repaints. 03298 * 03299 * So the desktop check hack will counter-act the invalidate 03300 * RDW_NOCHILDREN case if all windows are hiding / showing and the 03301 * desktop is being invalidated. Note that in the no RDW_NOCHILDREN 03302 * case, the invalid area gets distributed to the children first (in 03303 * this case, children of the desktop), so if the children cover the 03304 * desktop, the desktop won't get any invalid region, which is what 03305 * we want. - scottlu 03306 */ 03307 03308 /* 03309 * With the parameters we use InternalInvalidate() does not leave 03310 * the critical section 03311 */ 03312 03313 DWORD dwFlags = RDW_INVALIDATE | RDW_ERASE; 03314 if (cwndShowing == psmwp->ccvr && 03315 pwndParent != PWNDDESKTOP(pwndParent)) { 03316 dwFlags |= RDW_NOCHILDREN; 03317 } else { 03318 dwFlags |= RDW_ALLCHILDREN; 03319 } 03320 if (fInvalidateLayers) { 03321 dwFlags |= RDW_INVALIDATELAYERS; 03322 } 03323 03324 BEGINATOMICCHECK(); 03325 xxxInternalInvalidate(pwndParent, hrgnInvalidate, dwFlags); 03326 ENDATOMICCHECK(); 03327 } 03328 03329 /* 03330 * Since zzzInvalidateDCCache was called with IDC_MOVEBLT specified, 03331 * we must complete the WNDOBJ notification with a call to 03332 * GreClientRgnDone. 03333 * 03334 * Note: in zzzInvalidateDCCache, it is necessary to call 03335 * GreClientRgnUpdated even if gcountPWO is 0. However, 03336 * GreClientRgnDone only does something if gcountPWO is non-zero, 03337 * so we can optimize slightly. 03338 */ 03339 if (gcountPWO != 0) { 03340 GreClientRgnDone(GCR_WNDOBJEXISTS); 03341 } 03342 03343 UnlockAndExit: 03344 03345 /* 03346 * If necessary, release the screen DC 03347 */ 03348 if (hdcScreen != NULL) { 03349 03350 /* 03351 * Reset the visrgn before we go... 03352 */ 03353 GreSelectVisRgn(hdcScreen, NULL, SVR_DELETEOLD); 03354 03355 /* 03356 * Make sure that the drawing we did in this DC does not affect 03357 * any SPBs. Clear the dirty rect. 03358 */ 03359 GreGetBounds(hdcScreen, NULL, 0); // NULL means reset 03360 } 03361 03362 /* 03363 * All the dirty work is done. Ok to leave the critsects we entered 03364 * earlier and dispatch any deferred Window Event notifications. 03365 */ 03366 GreUnlockDisplay(gpDispInfo->hDev); 03367 zzzEndDeferWinEventNotify(); 03368 03369 return fSyncPaint; 03370 }

VOID zzzChangeStates PWND  pwndParent,
PSMWP  psmwp
 

Definition at line 1955 of file swp.c.

References tagSMWP::acvr, BEGINATOMICCHECK, BOOL, tagSMWP::bShellNotify, BYTE, tagSMWP::ccvr, CFSAVEBITS, ClrWF, CreateSpb(), tagCVR::cxClientNew, cy, tagCVR::cyClientNew, tagCVR::dxBlt, tagCVR::dyBlt, ENDATOMICCHECK, FALSE, FLayeredOrRedirected(), FWINABLE, GETPTI, gpDispInfo, grpdeskRitInput, tagDISPLAYINFO::hdcScreen, tagDISPLAYINFO::hDev, HIBYTE, HRGN_FULL, tagCVR::hrgnClip, tagWND::hrgnClip, tagWND::hrgnUpdate, tagCVR::hrgnVisOld, IntersectRect(), IsSmallerThanScreen(), IsStillWindowC(), IsTrayWindow(), LinkWindow(), LOBYTE, NULL, OffsetChildren(), PBYTE, tagCVR::pos, PtiCurrent, PtoHq, PWInsertAfter(), PWNDDESKTOP, tagWND::rcClient, tagWND::rcWindow, RecreateRedirectionBitmap(), RevalidateHwnd, SelectWindowRgn(), SetVisible(), SetWF, tagCARET::spwnd, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, SV_CLRFTRUEVIS, SV_SET, SV_UNSET, SWP_BOZO, TestCF, TestWF, ThreadLockAlways, ThreadUnlock, TRUE, UnlinkWindow(), ValidateWindowPos(), ValidateZorder(), VOID(), WEF_USEPWNDTHREAD, WEFLAYERED, WEFTOPMOST, WFFRAMEON, WFFULLSCREEN, WFMAXFAKEREGIONAL, WFSENDNCPAINT, WFTOGGLETOPMOST, WFVISIBLE, WFWIN31COMPAT, tagCARET::x, tagCVR::xClientNew, tagCARET::y, tagCVR::yClientNew, zzzCalcStartCursorHide(), and zzzWindowEvent.

Referenced by zzzBltValidBits().

01958 { 01959 int ccvr; 01960 PCVR pcvr; 01961 PWND pwnd; 01962 TL tlpwnd; 01963 TL tlpwndParent; 01964 int czorder = 0; 01965 01966 BEGINATOMICCHECK(); 01967 ThreadLockAlways(pwndParent, &tlpwndParent); 01968 01969 /* 01970 * Check that the sibbling list looks OK right now 01971 * 01972 * Here's the reason why this DBG code is commented out: 01973 * Owned windows are always expected to be on top of the owner. 01974 * However, an app can call SetWindowPos and insert the ownee after 01975 * the owner. IME somehow does this too. 01976 * This causes us to have A to be inserted after B and later in the 01977 * windowpos array, B to be inserted somewhere else. Hence, A won't be in the 01978 * expected position, because B will be moved after A is inserted. 01979 * In other words, a window in hwndInsertAfter must not appear later 01980 * as a hwnd to be z-ordered. Ownees below owners cause this situation. 01981 */ 01982 // DBGValidateSibblingZOrder(pwndParent); 01983 01984 01985 /* 01986 * Now change the window states 01987 */ 01988 for (pcvr = psmwp->acvr, ccvr = psmwp->ccvr; --ccvr >= 0; pcvr++) { 01989 01990 if (pcvr->pos.hwnd == NULL) 01991 continue; 01992 01993 UserAssert(0 == (pcvr->pos.flags & SWP_NOTIFYALL)); 01994 01995 pwnd = RevalidateHwnd(pcvr->pos.hwnd); 01996 01997 if ((pwnd == NULL) || !IsStillWindowC(pcvr->pos.hwndInsertAfter)) { 01998 RIPMSG0(RIP_WARNING, "zzzChangeStates: Window went away in middle"); 01999 pcvr->pos.flags = SWP_NOREDRAW | SWP_NOCHANGE; 02000 pcvr->pos.hwnd = NULL; 02001 } 02002 02003 #if DBG 02004 /* 02005 * This can happen when we get re-entered during a callback or mulitple 02006 * threads are z-ordering the same window. The tray does stuff like this. 02007 * We would need to keep the toggle state in the windowpos structure to 02008 * have each call have its own state. 02009 */ 02010 if (TestWF(pwnd, WFTOGGLETOPMOST) && (pcvr->pos.flags & SWP_NOZORDER)) 02011 RIPMSG0(RIP_WARNING, "zzzChangeState: WFTOGGLETOPMOST should not be set"); 02012 02013 // UserAssert(!(TestWF(pwnd, WFTOGGLETOPMOST) && (pcvr->pos.flags & SWP_NOZORDER))); 02014 #endif 02015 02016 /* 02017 * Check to se if there is any state to change. If not, just 02018 * continue. 02019 */ 02020 if ((pcvr->pos.flags & SWP_CHANGEMASK) == SWP_NOCHANGE) { 02021 02022 pcvr->pos.flags |= SWP_NOREDRAW; 02023 continue; 02024 } 02025 02026 /* 02027 * Change the window region if needed 02028 * 02029 * Before we do anything, check to see if we're only Z-ordering. 02030 * If so, then check to see if we're already in the right place, 02031 * and if so, clear the ZORDER flag. 02032 * 02033 * We have to make this test in the state-change loop if previous 02034 * windows in the WINDOWPOS list were Z-ordered, since the test depends 02035 * on any ordering that may have happened previously. 02036 * 02037 * We don't bother to do this redundancy check if there are 02038 * other bits set, because the amount of time saved in that 02039 * case is about as much as the amount of time it takes to 02040 * test for redundancy. 02041 */ 02042 if (((pcvr->pos.flags & SWP_CHANGEMASK) == 02043 (SWP_NOCHANGE & ~SWP_NOZORDER))) { 02044 02045 /* 02046 * If the window's Z order won't be changing, then 02047 * we can clear the ZORDER bit and set NOREDRAW. 02048 */ 02049 if ((!TestWF(pwnd, WFTOGGLETOPMOST)) && ValidateZorder(pcvr)) { 02050 02051 /* 02052 * The window's already in the right place: 02053 * Set SWP_NOZORDER bit, set SWP_NOREDRAW, 02054 * and destroy the visrgn that we created earlier. 02055 */ 02056 pcvr->pos.flags |= SWP_NOZORDER | SWP_NOREDRAW; 02057 02058 if (pcvr->hrgnVisOld) { 02059 GreDeleteObject(pcvr->hrgnVisOld); 02060 pcvr->hrgnVisOld = NULL; 02061 } 02062 continue; 02063 } 02064 } 02065 02066 /* 02067 * Change the window state, as appropriate... 02068 */ 02069 if ((pcvr->pos.flags & 02070 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)) != 02071 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)) { 02072 02073 PCARET pcaret = &PtiCurrent()->pq->caret; 02074 BOOL fRecreateRedirectionBitmap = FALSE; 02075 02076 if (FLayeredOrRedirected(pwnd)) { 02077 int cx = pwnd->rcWindow.right - pwnd->rcWindow.left; 02078 int cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top; 02079 02080 if (cx != pcvr->pos.cx || cy != pcvr->pos.cy) { 02081 fRecreateRedirectionBitmap = TRUE; 02082 } 02083 } 02084 02085 /* 02086 * Set up the new window and client rectangles. 02087 */ 02088 pwnd->rcWindow.left = pcvr->pos.x; 02089 pwnd->rcWindow.top = pcvr->pos.y; 02090 if (pwndParent != PWNDDESKTOP(pwnd)) { 02091 pwnd->rcWindow.left += pwndParent->rcClient.left; 02092 pwnd->rcWindow.top += pwndParent->rcClient.top; 02093 } 02094 02095 pwnd->rcWindow.right = pwnd->rcWindow.left + pcvr->pos.cx; 02096 pwnd->rcWindow.bottom = pwnd->rcWindow.top + pcvr->pos.cy; 02097 02098 if (pwnd->rcWindow.right < pwnd->rcWindow.left) { 02099 RIPMSG1(RIP_WARNING, "SWP: cx changed for pwnd %#p", pwnd); 02100 pwnd->rcWindow.right = pwnd->rcWindow.left; 02101 } 02102 02103 if (pwnd->rcWindow.bottom < pwnd->rcWindow.top) { 02104 RIPMSG1(RIP_WARNING, "SWP: cy changed for pwnd %#p", pwnd); 02105 pwnd->rcWindow.bottom = pwnd->rcWindow.top; 02106 } 02107 02108 /* 02109 * If the client moved relative to its parent, 02110 * offset the caret by the amount that rcBlt moved 02111 * relative to the client rect. 02112 */ 02113 if (pwnd == pcaret->spwnd) { 02114 02115 /* 02116 * Calculate the distance the contents of the client area 02117 * is moving, in client-relative coordinates. 02118 * 02119 * Calculates dBlt + (old position - new position) 02120 */ 02121 int dx = pcvr->dxBlt + pwnd->rcClient.left - pcvr->xClientNew; 02122 int dy = pcvr->dyBlt + pwnd->rcClient.top - pcvr->yClientNew; 02123 02124 if (pwndParent != PWNDDESKTOP(pwnd)) 02125 { 02126 dx -= pwndParent->rcClient.left; 02127 dy -= pwndParent->rcClient.top; 02128 } 02129 02130 if ((dx | dy) != 0) { 02131 pcaret->x += dx; 02132 pcaret->y += dy; 02133 } 02134 } 02135 02136 /* 02137 * Set up the new client rect 02138 * coordinates provided. 02139 */ 02140 pwnd->rcClient.left = pcvr->xClientNew; 02141 pwnd->rcClient.top = pcvr->yClientNew; 02142 if (pwndParent != PWNDDESKTOP(pwnd)) 02143 { 02144 pwnd->rcClient.left += pwndParent->rcClient.left; 02145 pwnd->rcClient.top += pwndParent->rcClient.top; 02146 } 02147 02148 pwnd->rcClient.right = pwnd->rcClient.left + pcvr->cxClientNew; 02149 pwnd->rcClient.bottom = pwnd->rcClient.top + pcvr->cyClientNew; 02150 02151 /* 02152 * If the window becomes smaller than the monitor, the system 02153 * allows it to be moved (see SetSysMenu) and so we must remove 02154 * the monitor region. 02155 */ 02156 if (TestWF(pwnd, WFMAXFAKEREGIONAL) && IsSmallerThanScreen(pwnd)) { 02157 SelectWindowRgn(pwnd, NULL); 02158 } 02159 02160 /* 02161 * If the layered window is resizing, try to resize the 02162 * redirection bitmap associated with it. 02163 */ 02164 if (fRecreateRedirectionBitmap) { 02165 RecreateRedirectionBitmap(pwnd); 02166 } 02167 02168 /* 02169 * Offset the absolute positions of the window's update region, 02170 * and the position and update regions of its children. 02171 */ 02172 if ((pcvr->dxBlt | pcvr->dyBlt) != 0) { 02173 /* 02174 * Change position of window region, if it has one 02175 * and it isn't a monitor region for a maximized window 02176 */ 02177 if ( pwnd->hrgnClip > HRGN_FULL && 02178 !TestWF(pwnd, WFMAXFAKEREGIONAL)) { 02179 GreOffsetRgn(pwnd->hrgnClip, pcvr->dxBlt, pcvr->dyBlt); 02180 } 02181 02182 if (pwnd->hrgnUpdate > HRGN_FULL) { 02183 GreOffsetRgn(pwnd->hrgnUpdate, pcvr->dxBlt, pcvr->dyBlt); 02184 } 02185 OffsetChildren(pwnd, pcvr->dxBlt, pcvr->dyBlt, NULL); 02186 02187 /* 02188 * Change the position of the sprite associated with 02189 * this window. 02190 */ 02191 if (TestWF(pwnd, WEFLAYERED)) { 02192 POINT ptPos = {pcvr->pos.x, pcvr->pos.y}; 02193 02194 GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, NULL, 02195 &ptPos, NULL, NULL, NULL, 0, NULL, 0, NULL); 02196 } 02197 } 02198 } 02199 02200 /* 02201 * Change the Z order if the flag is set. Revalidate 02202 * hwndInsertAfter to make sure that it is still valid 02203 */ 02204 if (!(pcvr->pos.flags & SWP_NOZORDER)) { 02205 02206 if (ValidateWindowPos(pcvr, pwndParent)) { 02207 02208 UnlinkWindow(pwnd, pwndParent); 02209 02210 LinkWindow(pwnd, 02211 PWInsertAfter(pcvr->pos.hwndInsertAfter), 02212 pwndParent); 02213 czorder++; 02214 02215 /* 02216 * HACK ALERT MERGE 02217 * 02218 * ValidateZOrder() depends on rational, consistent setting of the 02219 * WEFTOPMOST bit in order for it to work properly. What this means 02220 * is that we can't set or clear these bits ahead of time based on 02221 * where the window is moving to: instead we have to change the bit 02222 * after we've moved it. Enter the WFTOGGLETOPMOST bit: that bit 02223 * is set in ZOrderByOwner() based on what the topmost bit will 02224 * eventually be set to. To maintain a consistent state, we make 02225 * any changes AFTER the window has been Z-ordered. 02226 */ 02227 if (TestWF(pwnd, WFTOGGLETOPMOST)) { 02228 PBYTE pb; 02229 02230 ClrWF(pwnd, WFTOGGLETOPMOST); 02231 pb = ((BYTE *)&pwnd->state); 02232 pb[HIBYTE(WEFTOPMOST)] ^= LOBYTE(WEFTOPMOST); 02233 } 02234 } else { 02235 pcvr->pos.flags |= SWP_NOZORDER; 02236 ClrWF(pwnd, WFTOGGLETOPMOST); 02237 } 02238 } 02239 02240 02241 /* 02242 * Handle SWP_HIDEWINDOW and SWP_SHOWWINDOW, by clearing or setting 02243 * the WS_VISIBLE bit. 02244 */ 02245 UserAssert(pwndParent != NULL); 02246 ThreadLockAlways(pwnd, &tlpwnd); 02247 if (pcvr->pos.flags & SWP_SHOWWINDOW) { 02248 02249 /* 02250 * Window is showing. If this app is still in startup mode, 02251 * (still starting), give the the app starting cursor 5 more 02252 * seconds. 02253 */ 02254 if (GETPTI(pwnd)->ppi->W32PF_Flags & W32PF_APPSTARTING) 02255 zzzCalcStartCursorHide((PW32PROCESS)GETPTI(pwnd)->ppi, 5000); 02256 02257 /* 02258 * Set the WS_VISIBLE bit. 02259 */ 02260 SetVisible(pwnd, SV_SET); 02261 02262 if (FWINABLE()) 02263 zzzWindowEvent(EVENT_OBJECT_SHOW, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, WEF_USEPWNDTHREAD); 02264 02265 if (IsTrayWindow(pwnd)) { 02266 psmwp->bShellNotify = TRUE; 02267 pcvr->pos.flags |= TestWF(pwnd, WFFRAMEON) ? SWP_NOTIFYACTIVATE|SWP_NOTIFYCREATE: SWP_NOTIFYCREATE; 02268 02269 /* 02270 * This Chicago code is replaced by the preceding code, 02271 * which exits the critical section only after the Gre 02272 * lock is removed. Fritz 02273 * 02274 * xxxCallHook(HSHELL_WINDOWCREATED, 02275 * (WPARAM)HWq(pwnd), 02276 * (LPARAM)0, 02277 * WH_SHELL); 02278 * 02279 * PostShellHookMessages(HSHELL_WINDOWCREATED, pwnd); 02280 * 02281 * if (TestWF(pwnd, WFFRAMEON)) { 02282 * 02283 * xxxSetTrayWindow(pwnd); 02284 */ 02285 02286 } else if (TestWF(pwnd, WFFULLSCREEN)) { 02287 /* 02288 * Wake up the tray so it can notice that there is now 02289 * a fullscreen visible window. This deals with bugs 02290 * 32164, 141563, and 150217. FritzS 02291 */ 02292 psmwp->bShellNotify = TRUE; 02293 pcvr->pos.flags |= SWP_NOTIFYFS; 02294 } 02295 02296 /* 02297 * If we're redrawing, create an SPB for this window if 02298 * needed. 02299 */ 02300 if (!(pcvr->pos.flags & SWP_NOREDRAW) || 02301 (pcvr->pos.flags & SWP_CREATESPB)) { 02302 02303 /* 02304 * ONLY create an SPB if this window happens to be 02305 * on TOP of all others. NOTE: We could optimize this by 02306 * passing in the new vis rgn to CreateSpb() so that the 02307 * non-visible part of the window is automatically 02308 * invalid in the SPB. 02309 */ 02310 /* 02311 * Make sure this window's desktop is on top ! 02312 */ 02313 if (TestCF(pwnd, CFSAVEBITS) && 02314 pwnd->head.rpdesk == grpdeskRitInput) { 02315 02316 /* 02317 * If this window is the topmost VISIBLE window, 02318 * then we can create an SPB. 02319 */ 02320 PWND pwndT; 02321 RECT rcT; 02322 02323 for (pwndT = pwnd->spwndParent->spwndChild ; 02324 pwndT; 02325 pwndT = pwndT->spwndNext) { 02326 02327 if (pwndT == pwnd) { 02328 CreateSpb(pwnd, FALSE, gpDispInfo->hdcScreen); 02329 break; 02330 } 02331 02332 if (TestWF(pwndT, WFVISIBLE)) { 02333 02334 /* 02335 * Does this window intersect the SAVEBITS 02336 * window at all? If so, bail out. 02337 */ 02338 if (IntersectRect(&rcT, 02339 &pwnd->rcWindow, 02340 &pwndT->rcWindow)) { 02341 break; 02342 } 02343 } 02344 } 02345 } 02346 } 02347 02348 } else if (pcvr->pos.flags & SWP_HIDEWINDOW) { 02349 02350 /* 02351 * for idiots like MS-Access 2.0 who SetWindowPos( SWP_BOZO 02352 * and blow away themselves on the shell, then lets 02353 * just ignore their plea to be removed from the tray 02354 */ 02355 if (((pcvr->pos.flags & SWP_BOZO ) != SWP_BOZO) && 02356 IsTrayWindow(pwnd)) { 02357 02358 psmwp->bShellNotify = TRUE; 02359 pcvr->pos.flags |= SWP_NOTIFYDESTROY; 02360 02361 /* 02362 * This Chicago code is replaced by the preceding code, 02363 * which exits the critical section only after the Gre 02364 * lock is removed. Fritz 02365 * 02366 * xxxCallHook(HSHELL_WINDOWDESTROYED, 02367 * (WPARAM)HWq(pwnd), 02368 * (LPARAM)0, 02369 * WH_SHELL); 02370 * 02371 * PostShellHookMessages(HSHELL_WINDOWDESTROYED, pwnd); 02372 */ 02373 } 02374 02375 /* 02376 * Clear the WS_VISIBLE bit. 02377 */ 02378 SetVisible(pwnd, SV_UNSET | SV_CLRFTRUEVIS); 02379 02380 if (FWINABLE()) 02381 zzzWindowEvent(EVENT_OBJECT_HIDE, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, WEF_USEPWNDTHREAD); 02382 } 02383 02384 /* 02385 * BACKWARD COMPATIBILITY HACK 02386 * 02387 * Under 3.0, window frames were always redrawn, even if 02388 * SWP_NOREDRAW was specified. If we've gotten this far 02389 * and we're visible, and SWP_NOREDRAW was specified, set 02390 * the WFSENDNCPAINT bit. 02391 * 02392 * Apps such as ABC Flowcharter and 123W assume this. 02393 * Typical offending code is MoveWindow(pwnd, ..., FALSE); 02394 * followed by InvalidateRect(pwnd, NULL, TRUE); 02395 */ 02396 if (TestWF(pwnd, WFVISIBLE)) { 02397 if ((pcvr->pos.flags & SWP_STATECHANGE) || 02398 (!TestWF(pwnd, WFWIN31COMPAT) && (pcvr->pos.flags & SWP_NOREDRAW))) { 02399 02400 SetWF(pwnd, WFSENDNCPAINT); 02401 } 02402 } 02403 02404 /* 02405 * If this window has a clipping region set it now 02406 */ 02407 if (pcvr->hrgnClip != NULL) { 02408 SelectWindowRgn(pwnd, pcvr->hrgnClip); 02409 } 02410 ThreadUnlock(&tlpwnd); 02411 } 02412 02413 /* 02414 * Check that the sibbling list looks OK now that we're done 02415 */ 02416 // DBGValidateSibblingZOrder(pwndParent); 02417 02418 if (FWINABLE() && czorder) 02419 zzzWindowEvent(EVENT_OBJECT_REORDER, pwndParent, OBJID_CLIENT, INDEXID_CONTAINER, 0); 02420 ThreadUnlock(&tlpwndParent); 02421 02422 ENDATOMICCHECK(); 02423 }


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