1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Visibility computations 5 * FILE: win32ss/user/ntuser/vis.c 6 * PROGRAMMER: Ge van Geldorp (ge@gse.nl) 7 */ 8 9 #include <win32k.h> 10 DBG_DEFAULT_CHANNEL(UserWinpos); 11 12 PREGION FASTCALL 13 VIS_ComputeVisibleRegion( 14 PWND Wnd, 15 BOOLEAN ClientArea, 16 BOOLEAN ClipChildren, 17 BOOLEAN ClipSiblings) 18 { 19 PREGION VisRgn, ClipRgn; 20 PWND PreviousWindow, CurrentWindow, CurrentSibling; 21 22 if (!Wnd || !(Wnd->style & WS_VISIBLE)) 23 { 24 return NULL; 25 } 26 27 VisRgn = NULL; 28 29 if (ClientArea) 30 { 31 VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcClient); 32 } 33 else 34 { 35 VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow); 36 } 37 38 /* 39 * Walk through all parent windows and for each clip the visble region 40 * to the parent's client area and exclude all siblings that are over 41 * our window. 42 */ 43 44 PreviousWindow = Wnd; 45 CurrentWindow = Wnd->spwndParent; 46 while (CurrentWindow) 47 { 48 if (!VerifyWnd(CurrentWindow)) 49 { 50 ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow); 51 if (VisRgn) 52 REGION_Delete(VisRgn); 53 return NULL; 54 } 55 56 if (!(CurrentWindow->style & WS_VISIBLE)) 57 { 58 if (VisRgn) 59 REGION_Delete(VisRgn); 60 return NULL; 61 } 62 63 ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcClient); 64 IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); 65 REGION_Delete(ClipRgn); 66 67 if ((PreviousWindow->style & WS_CLIPSIBLINGS) || 68 (PreviousWindow == Wnd && ClipSiblings)) 69 { 70 CurrentSibling = CurrentWindow->spwndChild; 71 while ( CurrentSibling != NULL && 72 CurrentSibling != PreviousWindow ) 73 { 74 if ((CurrentSibling->style & WS_VISIBLE) && 75 !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT)) 76 { 77 ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentSibling->rcWindow); 78 /* Combine it with the window region if available */ 79 if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE)) 80 { 81 PREGION SiblingClipRgn = REGION_LockRgn(CurrentSibling->hrgnClip); 82 if (SiblingClipRgn) 83 { 84 REGION_bOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top); 85 IntGdiCombineRgn(ClipRgn, ClipRgn, SiblingClipRgn, RGN_AND); 86 REGION_bOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top); 87 REGION_UnlockRgn(SiblingClipRgn); 88 } 89 } 90 IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); 91 REGION_Delete(ClipRgn); 92 } 93 CurrentSibling = CurrentSibling->spwndNext; 94 } 95 } 96 97 PreviousWindow = CurrentWindow; 98 CurrentWindow = CurrentWindow->spwndParent; 99 } 100 101 if (ClipChildren) 102 { 103 CurrentWindow = Wnd->spwndChild; 104 while (CurrentWindow) 105 { 106 if ((CurrentWindow->style & WS_VISIBLE) && 107 !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT)) 108 { 109 ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcWindow); 110 /* Combine it with the window region if available */ 111 if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE)) 112 { 113 PREGION CurrentRgnClip = REGION_LockRgn(CurrentWindow->hrgnClip); 114 if (CurrentRgnClip) 115 { 116 REGION_bOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top); 117 IntGdiCombineRgn(ClipRgn, ClipRgn, CurrentRgnClip, RGN_AND); 118 REGION_bOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top); 119 REGION_UnlockRgn(CurrentRgnClip); 120 } 121 } 122 IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); 123 REGION_Delete(ClipRgn); 124 } 125 CurrentWindow = CurrentWindow->spwndNext; 126 } 127 } 128 129 if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE)) 130 { 131 PREGION WndRgnClip = REGION_LockRgn(Wnd->hrgnClip); 132 if (WndRgnClip) 133 { 134 REGION_bOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top); 135 IntGdiCombineRgn(VisRgn, VisRgn, WndRgnClip, RGN_AND); 136 REGION_bOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top); 137 REGION_UnlockRgn(WndRgnClip); 138 } 139 } 140 141 return VisRgn; 142 } 143 144 VOID FASTCALL 145 co_VIS_WindowLayoutChanged( 146 PWND Wnd, 147 PREGION NewlyExposed) 148 { 149 PWND Parent; 150 USER_REFERENCE_ENTRY Ref; 151 152 ASSERT_REFS_CO(Wnd); 153 154 Parent = Wnd->spwndParent; 155 if(Parent) 156 { 157 PREGION TempRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 158 159 if (!TempRgn) 160 return; 161 162 IntGdiCombineRgn(TempRgn, NewlyExposed, NULL, RGN_COPY); 163 REGION_bOffsetRgn(TempRgn, 164 Wnd->rcWindow.left - Parent->rcClient.left, 165 Wnd->rcWindow.top - Parent->rcClient.top); 166 167 UserRefObjectCo(Parent, &Ref); 168 co_UserRedrawWindow(Parent, NULL, TempRgn, 169 RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | 170 RDW_ALLCHILDREN); 171 UserDerefObjectCo(Parent); 172 173 REGION_Delete(TempRgn); 174 } 175 } 176 177 /* EOF */ 178