1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: GDI WNDOBJ Functions 5 * FILE: win32ss/gdi/eng/engwindow.c 6 * PROGRAMER: Gregor Anich 7 */ 8 9 #include <win32k.h> 10 #include <debug.h> 11 DBG_DEFAULT_CHANNEL(EngWnd); 12 13 INT gcountPWO = 0; 14 15 /* 16 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ 17 */ 18 VOID 19 FASTCALL 20 IntEngWndCallChangeProc( 21 _In_ EWNDOBJ *Clip, 22 _In_ FLONG flChanged) 23 { 24 if (Clip->ChangeProc == NULL) 25 { 26 return; 27 } 28 29 /* check flags of the WNDOBJ */ 30 flChanged &= Clip->Flags; 31 if (flChanged == 0) 32 { 33 return; 34 } 35 36 TRACE("Calling WNDOBJCHANGEPROC (0x%p), Changed = 0x%x\n", 37 Clip->ChangeProc, flChanged); 38 39 /* Call the WNDOBJCHANGEPROC */ 40 if (flChanged == WOC_CHANGED) 41 Clip->ChangeProc(NULL, flChanged); 42 else 43 Clip->ChangeProc((WNDOBJ *)Clip, flChanged); 44 } 45 46 /* 47 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WND 48 */ 49 BOOLEAN 50 FASTCALL 51 IntEngWndUpdateClipObj( 52 EWNDOBJ* Clip, 53 PWND Window) 54 { 55 PREGION visRgn; 56 57 TRACE("IntEngWndUpdateClipObj\n"); 58 59 visRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE); 60 if (visRgn != NULL) 61 { 62 if (visRgn->rdh.nCount > 0) 63 { 64 IntEngUpdateClipRegion((XCLIPOBJ*)Clip, visRgn->rdh.nCount, visRgn->Buffer, &visRgn->rdh.rcBound); 65 TRACE("Created visible region with %lu rects\n", visRgn->rdh.nCount); 66 TRACE(" BoundingRect: %d, %d %d, %d\n", 67 visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top, 68 visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom); 69 { 70 ULONG i; 71 for (i = 0; i < visRgn->rdh.nCount; i++) 72 { 73 TRACE(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1, 74 visRgn->Buffer[i].left, visRgn->Buffer[i].top, 75 visRgn->Buffer[i].right, visRgn->Buffer[i].bottom); 76 } 77 } 78 } 79 REGION_Delete(visRgn); 80 } 81 else 82 { 83 /* Fall back to client rect */ 84 IntEngUpdateClipRegion((XCLIPOBJ*)Clip, 1, &Window->rcClient, &Window->rcClient); 85 } 86 87 /* Update the WNDOBJ */ 88 Clip->rclClient = Window->rcClient; 89 Clip->iUniq++; 90 91 return TRUE; 92 } 93 94 /* 95 * Updates all WNDOBJs of the given WND and calls the change-procs. 96 */ 97 VOID 98 FASTCALL 99 IntEngWindowChanged( 100 _In_ PWND Window, 101 _In_ FLONG flChanged) 102 { 103 EWNDOBJ *Clip; 104 105 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL); 106 107 Clip = UserGetProp(Window, AtomWndObj, TRUE); 108 if (!Clip) 109 { 110 return; 111 } 112 113 ASSERT(Clip->Hwnd == Window->head.h); 114 // if (Clip->pvConsumer != NULL) 115 { 116 /* Update the WNDOBJ */ 117 switch (flChanged) 118 { 119 case WOC_RGN_CLIENT: 120 /* Update the clipobj and client rect of the WNDOBJ */ 121 IntEngWndUpdateClipObj(Clip, Window); 122 break; 123 124 case WOC_DELETE: 125 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */ 126 break; 127 } 128 129 /* Call the change proc */ 130 IntEngWndCallChangeProc(Clip, flChanged); 131 132 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */ 133 if (flChanged == WOC_RGN_CLIENT) 134 { 135 IntEngWndCallChangeProc(Clip, WOC_CHANGED); 136 } 137 } 138 } 139 140 /* 141 * @implemented 142 */ 143 WNDOBJ* 144 APIENTRY 145 EngCreateWnd( 146 SURFOBJ *pso, 147 HWND hWnd, 148 WNDOBJCHANGEPROC pfn, 149 FLONG fl, 150 int iPixelFormat) 151 { 152 EWNDOBJ *Clip = NULL; 153 WNDOBJ *WndObjUser = NULL; 154 PWND Window; 155 156 TRACE("EngCreateWnd: pso = 0x%p, hwnd = 0x%p, pfn = 0x%p, fl = 0x%lx, pixfmt = %d\n", 157 pso, hWnd, pfn, fl, iPixelFormat); 158 159 UserEnterExclusive(); 160 161 if (fl & (WO_RGN_WINDOW | WO_RGN_DESKTOP_COORD | WO_RGN_UPDATE_ALL)) 162 { 163 FIXME("Unsupported flags: 0x%lx\n", fl & ~(WO_RGN_CLIENT_DELTA | WO_RGN_CLIENT | WO_RGN_SURFACE_DELTA | WO_RGN_SURFACE)); 164 } 165 166 /* Get window object */ 167 Window = UserGetWindowObject(hWnd); 168 if (Window == NULL) 169 { 170 goto Exit; 171 } 172 173 /* Create WNDOBJ */ 174 Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof(EWNDOBJ), GDITAG_WNDOBJ); 175 if (Clip == NULL) 176 { 177 ERR("Failed to allocate memory for a WND structure!\n"); 178 goto Exit; 179 } 180 IntEngInitClipObj((XCLIPOBJ*)Clip); 181 182 /* Fill the clipobj */ 183 if (!IntEngWndUpdateClipObj(Clip, Window)) 184 { 185 EngFreeMem(Clip); 186 goto Exit; 187 } 188 189 /* Fill user object */ 190 WndObjUser = (WNDOBJ *)Clip; 191 WndObjUser->psoOwner = pso; 192 WndObjUser->pvConsumer = NULL; 193 194 /* Fill internal object */ 195 Clip->Hwnd = hWnd; 196 Clip->ChangeProc = pfn; 197 /* Keep track of relevant flags */ 198 Clip->Flags = fl & (WO_RGN_CLIENT_DELTA | WO_RGN_CLIENT | WO_RGN_SURFACE_DELTA | WO_RGN_SURFACE | WO_DRAW_NOTIFY); 199 if (fl & WO_SPRITE_NOTIFY) 200 Clip->Flags |= WOC_SPRITE_OVERLAP | WOC_SPRITE_NO_OVERLAP; 201 /* Those should always be sent */ 202 Clip->Flags |= WOC_CHANGED | WOC_DELETE; 203 Clip->PixelFormat = iPixelFormat; 204 205 /* associate object with window */ 206 UserSetProp(Window, AtomWndObj, Clip, TRUE); 207 ++gcountPWO; 208 209 TRACE("EngCreateWnd: SUCCESS: %p!\n", WndObjUser); 210 211 Exit: 212 UserLeave(); 213 return WndObjUser; 214 } 215 216 217 /* 218 * @implemented 219 */ 220 VOID 221 APIENTRY 222 EngDeleteWnd( 223 IN WNDOBJ *pwo) 224 { 225 EWNDOBJ* Clip = (EWNDOBJ *)pwo;//CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj); 226 PWND Window; 227 228 TRACE("EngDeleteWnd: pwo = 0x%p\n", pwo); 229 230 UserEnterExclusive(); 231 232 /* Get window object */ 233 Window = UserGetWindowObject(Clip->Hwnd); 234 if (Window == NULL) 235 { 236 ERR("Couldnt get window object for WndObjInt->Hwnd!!!\n"); 237 } 238 else 239 { 240 /* Remove object from window */ 241 UserRemoveProp(Window, AtomWndObj, TRUE); 242 } 243 --gcountPWO; 244 245 UserLeave(); 246 247 /* Free resources */ 248 IntEngFreeClipResources((XCLIPOBJ*)Clip); 249 EngFreeMem(Clip); 250 } 251 252 253 /* 254 * @implemented 255 */ 256 BOOL 257 APIENTRY 258 WNDOBJ_bEnum( 259 IN WNDOBJ *pwo, 260 IN ULONG cj, 261 OUT ULONG *pul) 262 { 263 /* Relay */ 264 return CLIPOBJ_bEnum(&pwo->coClient, cj, pul); 265 } 266 267 268 /* 269 * @implemented 270 */ 271 ULONG 272 APIENTRY 273 WNDOBJ_cEnumStart( 274 IN WNDOBJ *pwo, 275 IN ULONG iType, 276 IN ULONG iDirection, 277 IN ULONG cLimit) 278 { 279 /* Relay */ 280 // FIXME: Should we enumerate all rectangles or not? 281 return CLIPOBJ_cEnumStart(&pwo->coClient, FALSE, iType, iDirection, cLimit); 282 } 283 284 285 /* 286 * @implemented 287 */ 288 VOID 289 APIENTRY 290 WNDOBJ_vSetConsumer( 291 IN WNDOBJ *pwo, 292 IN PVOID pvConsumer) 293 { 294 EWNDOBJ* Clip = (EWNDOBJ *)pwo;//CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj); 295 BOOL Hack; 296 297 TRACE("WNDOBJ_vSetConsumer: pwo = 0x%p, pvConsumer = 0x%p\n", pwo, pvConsumer); 298 299 Hack = (pwo->pvConsumer == NULL); 300 pwo->pvConsumer = pvConsumer; 301 302 /* HACKHACKHACK 303 * 304 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state 305 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer 306 * in the callback to identify the WNDOBJ I think. 307 * 308 * - blight 309 */ 310 if (Hack) 311 { 312 FIXME("Is this hack really needed?\n"); 313 IntEngWndCallChangeProc(Clip, WOC_RGN_CLIENT); 314 IntEngWndCallChangeProc(Clip, WOC_CHANGED); 315 IntEngWndCallChangeProc(Clip, WOC_DRAWN); 316 } 317 } 318 319 /* EOF */ 320 321