Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwindc.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Win32k subsystem 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: subsystems/win32/win32k/ntuser/windc.c 00005 * PURPOSE: Window DC management 00006 * COPYRIGHT: Copyright 2007 ReactOS Team 00007 */ 00008 00009 #include <win32k.h> 00010 DBG_DEFAULT_CHANNEL(UserDce); 00011 00012 /* GLOBALS *******************************************************************/ 00013 00014 /* NOTE: I think we should store this per window station (including GDI objects) */ 00015 /* Answer: No, use the DCE pMonitor to compare with! */ 00016 00017 static LIST_ENTRY LEDce; 00018 static INT DCECount = 0; // Count of DCE in system. 00019 00020 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \ 00021 DCX_NORESETATTRS | DCX_LOCKWINDOWUPDATE | \ 00022 DCX_LAYEREDWIN | DCX_CACHE | DCX_WINDOW | \ 00023 DCX_PARENTCLIP) 00024 00025 /* FUNCTIONS *****************************************************************/ 00026 00027 INIT_FUNCTION 00028 NTSTATUS 00029 NTAPI 00030 InitDCEImpl(VOID) 00031 { 00032 InitializeListHead(&LEDce); 00033 return STATUS_SUCCESS; 00034 } 00035 00036 // 00037 // This should be moved to dc.c or dcutil.c. 00038 // 00039 HDC FASTCALL 00040 DceCreateDisplayDC(VOID) 00041 { 00042 UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY"); 00043 00044 co_IntGraphicsCheck(TRUE); 00045 00046 return IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE); 00047 } 00048 00049 static 00050 HRGN FASTCALL 00051 DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags) 00052 { 00053 HRGN VisRgn; 00054 00055 VisRgn = VIS_ComputeVisibleRegion( Window, 00056 0 == (Flags & DCX_WINDOW), 00057 0 != (Flags & DCX_CLIPCHILDREN), 00058 0 != (Flags & DCX_CLIPSIBLINGS)); 00059 00060 if (VisRgn == NULL) 00061 VisRgn = IntSysCreateRectRgn(0, 0, 0, 0); 00062 00063 return VisRgn; 00064 } 00065 00066 PDCE FASTCALL 00067 DceAllocDCE(PWND Window OPTIONAL, DCE_TYPE Type) 00068 { 00069 PDCE pDce; 00070 00071 pDce = ExAllocatePoolWithTag(PagedPool, sizeof(DCE), USERTAG_DCE); 00072 if(!pDce) 00073 return NULL; 00074 00075 pDce->hDC = DceCreateDisplayDC(); 00076 if (!pDce->hDC) 00077 { 00078 ExFreePoolWithTag(pDce, USERTAG_DCE); 00079 return NULL; 00080 } 00081 DCECount++; 00082 TRACE("Alloc DCE's! %d\n",DCECount); 00083 pDce->hwndCurrent = (Window ? Window->head.h : NULL); 00084 pDce->pwndOrg = Window; 00085 pDce->pwndClip = Window; 00086 pDce->hrgnClip = NULL; 00087 pDce->hrgnClipPublic = NULL; 00088 pDce->hrgnSavedVis = NULL; 00089 pDce->ppiOwner = NULL; 00090 00091 InsertTailList(&LEDce, &pDce->List); 00092 00093 DCU_SetDcUndeletable(pDce->hDC); 00094 00095 if (Type == DCE_WINDOW_DC || Type == DCE_CLASS_DC) // Window DCE have ownership. 00096 { 00097 pDce->ptiOwner = GetW32ThreadInfo(); 00098 } 00099 else 00100 { 00101 TRACE("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce->hDC); 00102 GreSetDCOwner(pDce->hDC, GDI_OBJ_HMGR_NONE); 00103 pDce->ptiOwner = NULL; 00104 } 00105 00106 if (Type == DCE_CACHE_DC) 00107 { 00108 pDce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY; 00109 } 00110 else 00111 { 00112 pDce->DCXFlags = DCX_DCEBUSY; 00113 if (Window) 00114 { 00115 if (Type == DCE_WINDOW_DC) 00116 { 00117 if (Window->style & WS_CLIPCHILDREN) pDce->DCXFlags |= DCX_CLIPCHILDREN; 00118 if (Window->style & WS_CLIPSIBLINGS) pDce->DCXFlags |= DCX_CLIPSIBLINGS; 00119 } 00120 } 00121 } 00122 return(pDce); 00123 } 00124 00125 static VOID APIENTRY 00126 DceSetDrawable( PWND Window OPTIONAL, 00127 HDC hDC, 00128 ULONG Flags, 00129 BOOL SetClipOrigin) 00130 { 00131 DC *dc = DC_LockDc(hDC); 00132 if(!dc) 00133 return; 00134 00135 if (Window == NULL) 00136 { 00137 dc->ptlDCOrig.x = 0; 00138 dc->ptlDCOrig.y = 0; 00139 } 00140 else 00141 { 00142 if (Flags & DCX_WINDOW) 00143 { 00144 dc->ptlDCOrig.x = Window->rcWindow.left; 00145 dc->ptlDCOrig.y = Window->rcWindow.top; 00146 } 00147 else 00148 { 00149 dc->ptlDCOrig.x = Window->rcClient.left; 00150 dc->ptlDCOrig.y = Window->rcClient.top; 00151 } 00152 } 00153 DC_UnlockDc(dc); 00154 } 00155 00156 00157 static VOID FASTCALL 00158 DceDeleteClipRgn(DCE* Dce) 00159 { 00160 Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN); 00161 00162 if (Dce->DCXFlags & DCX_KEEPCLIPRGN ) 00163 { 00164 Dce->DCXFlags &= ~DCX_KEEPCLIPRGN; 00165 } 00166 else if (Dce->hrgnClip != NULL) 00167 { 00168 GreDeleteObject(Dce->hrgnClip); 00169 } 00170 00171 Dce->hrgnClip = NULL; 00172 00173 /* Make it dirty so that the vis rgn gets recomputed next time */ 00174 Dce->DCXFlags |= DCX_DCEDIRTY; 00175 } 00176 00177 static INT FASTCALL 00178 DceReleaseDC(DCE* dce, BOOL EndPaint) 00179 { 00180 if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_INDESTROY | DCX_DCEEMPTY | DCX_DCEBUSY))) 00181 { 00182 return 0; 00183 } 00184 00185 /* Restore previous visible region */ 00186 if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) && 00187 ((dce->DCXFlags & DCX_CACHE) || EndPaint)) 00188 { 00189 DceDeleteClipRgn(dce); 00190 } 00191 00192 if (dce->DCXFlags & DCX_CACHE) 00193 { 00194 if (!(dce->DCXFlags & DCX_NORESETATTRS)) 00195 { 00196 /* Make the DC clean so that SetDCState doesn't try to update the vis rgn */ 00197 IntGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN); 00198 00199 // Clean the DC 00200 if (!IntGdiCleanDC(dce->hDC)) return 0; 00201 00202 if (dce->DCXFlags & DCX_DCEDIRTY) 00203 { 00204 /* Don't keep around invalidated entries 00205 * because SetDCState() disables hVisRgn updates 00206 * by removing dirty bit. */ 00207 dce->hwndCurrent = 0; 00208 dce->DCXFlags &= DCX_CACHE; 00209 dce->DCXFlags |= DCX_DCEEMPTY; 00210 } 00211 } 00212 dce->DCXFlags &= ~DCX_DCEBUSY; 00213 TRACE("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce->hDC); 00214 if (!GreSetDCOwner(dce->hDC, GDI_OBJ_HMGR_NONE)) 00215 return 0; 00216 dce->ptiOwner = NULL; // Reset ownership. 00217 dce->ppiOwner = NULL; 00218 00219 #if 0 // Need to research and fix before this is a "growing" issue. 00220 if (++DCECache > 32) 00221 { 00222 pLE = LEDce.Flink; 00223 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00224 do 00225 { 00226 if (!(pDCE->DCXFlags & DCX_DCEBUSY)) 00227 { /* Free the unused cache DCEs. */ 00228 pDCE = DceFreeDCE(pDCE, TRUE); 00229 if (!pDCE) break; 00230 continue; 00231 } 00232 } 00233 while (pLE != &LEDce ); 00234 } 00235 #endif 00236 } 00237 return 1; // Released! 00238 } 00239 00240 static VOID FASTCALL 00241 DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags) 00242 { 00243 HANDLE hRgnVisible = NULL; 00244 ULONG DcxFlags; 00245 PWND DesktopWindow; 00246 00247 if (Flags & DCX_PARENTCLIP) 00248 { 00249 PWND Parent; 00250 00251 Parent = Window->spwndParent; 00252 if(!Parent) 00253 { 00254 hRgnVisible = NULL; 00255 goto noparent; 00256 } 00257 00258 if (Parent->style & WS_CLIPSIBLINGS) 00259 { 00260 DcxFlags = DCX_CLIPSIBLINGS | 00261 (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW)); 00262 } 00263 else 00264 { 00265 DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW); 00266 } 00267 hRgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->head.h, Flags); 00268 } 00269 else if (Window == NULL) 00270 { 00271 DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); 00272 if (NULL != DesktopWindow) 00273 { 00274 hRgnVisible = IntSysCreateRectRgnIndirect(&DesktopWindow->rcWindow); 00275 } 00276 else 00277 { 00278 hRgnVisible = NULL; 00279 } 00280 } 00281 else 00282 { 00283 hRgnVisible = DceGetVisRgn(Window, Flags, 0, 0); 00284 } 00285 00286 noparent: 00287 if (Flags & DCX_INTERSECTRGN) 00288 { 00289 if(Dce->hrgnClip != NULL) 00290 { 00291 NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hrgnClip, RGN_AND); 00292 } 00293 else 00294 { 00295 if(hRgnVisible != NULL) 00296 { 00297 GreDeleteObject(hRgnVisible); 00298 } 00299 hRgnVisible = IntSysCreateRectRgn(0, 0, 0, 0); 00300 } 00301 } 00302 else if (Flags & DCX_EXCLUDERGN && Dce->hrgnClip != NULL) 00303 { 00304 NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hrgnClip, RGN_DIFF); 00305 } 00306 00307 Dce->DCXFlags &= ~DCX_DCEDIRTY; 00308 GdiSelectVisRgn(Dce->hDC, hRgnVisible); 00309 00310 if (Window != NULL) 00311 { 00312 IntEngWindowChanged(Window, WOC_RGN_CLIENT); 00313 } 00314 00315 if (hRgnVisible != NULL) 00316 { 00317 GreDeleteObject(hRgnVisible); 00318 } 00319 } 00320 00321 HDC FASTCALL 00322 UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags) 00323 { 00324 PWND Parent; 00325 ULONG DcxFlags; 00326 DCE* Dce = NULL; 00327 BOOL UpdateClipOrigin = FALSE; 00328 HDC hDC = NULL; 00329 PPROCESSINFO ppi; 00330 PLIST_ENTRY pLE; 00331 00332 if (NULL == Wnd) 00333 { 00334 Flags &= ~DCX_USESTYLE; 00335 Flags |= DCX_CACHE; 00336 } 00337 00338 if (Flags & (DCX_WINDOW | DCX_PARENTCLIP)) Flags |= DCX_CACHE; 00339 00340 // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set. 00341 if (Flags & DCX_USESTYLE) 00342 { 00343 Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP); 00344 if (!(Flags & DCX_WINDOW)) // Not window rectangle 00345 { 00346 if (Wnd->pcls->style & CS_PARENTDC) 00347 { 00348 Flags |= DCX_PARENTCLIP; 00349 } 00350 00351 if (!(Flags & DCX_CACHE) && // Not on the cheap wine list. 00352 !(Wnd->pcls->style & CS_OWNDC) ) 00353 { 00354 if (!(Wnd->pcls->style & CS_CLASSDC)) 00355 // The window is not POWNED or has any CLASS, so we are looking for cheap wine. 00356 Flags |= DCX_CACHE; 00357 else 00358 { 00359 if (Wnd->pcls->pdce) hDC = ((PDCE)Wnd->pcls->pdce)->hDC; 00360 TRACE("We have CLASS!!\n"); 00361 } 00362 } 00363 /* else // For Testing! 00364 { 00365 DPRINT1("We have POWNER!!\n"); 00366 if (Window->Dce) DPRINT1("We have POWNER with DCE!!\n"); 00367 } 00368 */ 00369 if (Wnd->style & WS_CLIPSIBLINGS) 00370 { 00371 Flags |= DCX_CLIPSIBLINGS; 00372 } 00373 00374 if (Wnd->style & WS_CLIPCHILDREN && 00375 !(Wnd->style & WS_MINIMIZE)) 00376 { 00377 Flags |= DCX_CLIPCHILDREN; 00378 } 00379 /* If minized with icon in the set, we are forced to be cheap! */ 00380 if (Wnd->style & WS_MINIMIZE && 00381 Wnd->pcls->hIcon) 00382 { 00383 Flags |= DCX_CACHE; 00384 } 00385 } 00386 else 00387 { 00388 if (Wnd->style & WS_CLIPSIBLINGS) Flags |= DCX_CLIPSIBLINGS; 00389 Flags |= DCX_CACHE; 00390 } 00391 } 00392 00393 if (Flags & DCX_WINDOW) Flags &= ~DCX_CLIPCHILDREN; 00394 00395 if (Flags & DCX_NOCLIPCHILDREN) 00396 { 00397 Flags |= DCX_CACHE; 00398 Flags &= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN); 00399 } 00400 00401 Parent = (Wnd ? Wnd->spwndParent : NULL); 00402 00403 if (NULL == Wnd || !(Wnd->style & WS_CHILD) || NULL == Parent) 00404 { 00405 Flags &= ~DCX_PARENTCLIP; 00406 Flags |= DCX_CLIPSIBLINGS; 00407 } 00408 00409 /* It seems parent clip is ignored when clipping siblings or children */ 00410 if (Flags & (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN)) Flags &= ~DCX_PARENTCLIP; 00411 00412 if (Flags & DCX_PARENTCLIP) 00413 { 00414 if ((Wnd->style & WS_VISIBLE) && 00415 (Parent->style & WS_VISIBLE)) 00416 { 00417 Flags &= ~DCX_CLIPCHILDREN; 00418 if (Parent->style & WS_CLIPSIBLINGS) 00419 { 00420 Flags |= DCX_CLIPSIBLINGS; 00421 } 00422 } 00423 } 00424 00425 // Window nz, check to see if we still own this or it is just cheap wine tonight. 00426 if (!(Flags & DCX_CACHE)) 00427 { 00428 if ( Wnd->head.pti != GetW32ThreadInfo()) 00429 Flags |= DCX_CACHE; // Ah~ Not Powned! Forced to be cheap~ 00430 } 00431 00432 DcxFlags = Flags & DCX_CACHECOMPAREMASK; 00433 00434 if (Flags & DCX_CACHE) 00435 { // Scan the cheap wine list for our match. 00436 DCE* DceEmpty = NULL; 00437 DCE* DceUnused = NULL; 00438 KeEnterCriticalRegion(); 00439 pLE = LEDce.Flink; 00440 Dce = CONTAINING_RECORD(pLE, DCE, List); 00441 do 00442 { 00443 // The reason for this you may ask? 00444 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window! 00445 // Need to test for null here. Not sure if this is a bug or a feature. 00446 // First time use hax, need to use DceAllocDCE during window display init. 00447 if (!Dce) break; 00448 // 00449 // The way I understand this, you can have more than one DC per window. 00450 // Only one Owned if one was requested and saved and one Cached. 00451 // 00452 if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE) 00453 { 00454 DceUnused = Dce; 00455 if (Dce->DCXFlags & DCX_DCEEMPTY) 00456 { 00457 DceEmpty = Dce; 00458 } 00459 else if (Dce->hwndCurrent == (Wnd ? Wnd->head.h : NULL) && 00460 ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags)) 00461 { 00462 UpdateClipOrigin = TRUE; 00463 break; 00464 } 00465 } 00466 pLE = Dce->List.Flink; 00467 Dce = CONTAINING_RECORD(pLE, DCE, List); 00468 } 00469 while (pLE != &LEDce); 00470 KeLeaveCriticalRegion(); 00471 00472 Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty; 00473 00474 if (Dce == NULL) 00475 { 00476 Dce = DceAllocDCE(NULL, DCE_CACHE_DC); 00477 } 00478 if (!Dce) return NULL; 00479 00480 Dce->hwndCurrent = (Wnd ? Wnd->head.h : NULL); 00481 } 00482 else // If we are here, we are POWNED or having CLASS. 00483 { 00484 KeEnterCriticalRegion(); 00485 pLE = LEDce.Flink; 00486 Dce = CONTAINING_RECORD(pLE, DCE, List); 00487 do 00488 { // Check for Window handle than HDC match for CLASS. 00489 if ((Dce->hwndCurrent == Wnd->head.h) || 00490 (Dce->hDC == hDC)) 00491 break; 00492 pLE = Dce->List.Flink; 00493 Dce = CONTAINING_RECORD(pLE, DCE, List); 00494 } 00495 while (pLE != &LEDce); 00496 KeLeaveCriticalRegion(); 00497 00498 if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) && 00499 (Dce->DCXFlags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) ) 00500 { 00501 DceDeleteClipRgn(Dce); 00502 } 00503 } 00504 // First time use hax, need to use DceAllocDCE during window display init. 00505 if (NULL == Dce) 00506 { 00507 return(NULL); 00508 } 00509 00510 if (!GreIsHandleValid(Dce->hDC)) 00511 { 00512 ERR("FIXME: Got DCE with invalid hDC! 0x%x\n", Dce->hDC); 00513 Dce->hDC = DceCreateDisplayDC(); 00514 /* FIXME: Handle error */ 00515 } 00516 00517 Dce->DCXFlags = Flags | DCX_DCEBUSY; 00518 00519 /* 00520 * Bump it up! This prevents the random errors in wine dce tests and with 00521 * proper bits set in DCX_CACHECOMPAREMASK. 00522 * Reference: 00523 * http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html 00524 * http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html 00525 */ 00526 if (pLE != &LEDce) 00527 { 00528 RemoveEntryList(&Dce->List); 00529 InsertHeadList(&LEDce, &Dce->List); 00530 } 00531 00532 /* Introduced in rev 6691 and modified later. */ 00533 if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion ) 00534 { 00535 Flags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN; 00536 Dce->DCXFlags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN; 00537 ClipRegion = Wnd->hrgnUpdate; 00538 } 00539 00540 if (ClipRegion == HRGN_WINDOW) 00541 { 00542 if (!(Flags & DCX_WINDOW)) 00543 { 00544 Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcClient); 00545 } 00546 else 00547 { 00548 Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcWindow); 00549 } 00550 Dce->DCXFlags &= ~DCX_KEEPCLIPRGN; 00551 } 00552 else if (ClipRegion != NULL) 00553 { 00554 if (Dce->hrgnClip != NULL) 00555 { 00556 ERR("Should not be called!!\n"); 00557 GreDeleteObject(Dce->hrgnClip); 00558 Dce->hrgnClip = NULL; 00559 } 00560 Dce->hrgnClip = ClipRegion; 00561 } 00562 00563 DceSetDrawable(Wnd, Dce->hDC, Flags, UpdateClipOrigin); 00564 00565 DceUpdateVisRgn(Dce, Wnd, Flags); 00566 00567 if (Dce->DCXFlags & DCX_CACHE) 00568 { 00569 TRACE("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce->hDC); 00570 // Need to set ownership so Sync dcattr will work. 00571 GreSetDCOwner(Dce->hDC, GDI_OBJ_HMGR_POWNED); 00572 Dce->ptiOwner = GetW32ThreadInfo(); // Set the temp owning 00573 } 00574 00575 if ( Wnd && 00576 Wnd->ExStyle & WS_EX_LAYOUTRTL && 00577 !(Flags & DCX_KEEPLAYOUT) ) 00578 { 00579 NtGdiSetLayout(Dce->hDC, -1, LAYOUT_RTL); 00580 } 00581 00582 if (Dce->DCXFlags & DCX_PROCESSOWNED) 00583 { 00584 ppi = PsGetCurrentProcessWin32Process(); 00585 ppi->W32PF_flags |= W32PF_OWNDCCLEANUP; 00586 Dce->ptiOwner = NULL; 00587 Dce->ppiOwner = ppi; 00588 } 00589 00590 return(Dce->hDC); 00591 } 00592 00593 /*********************************************************************** 00594 * DceFreeDCE 00595 */ 00596 PDCE FASTCALL 00597 DceFreeDCE(PDCE pdce, BOOLEAN Force) 00598 { 00599 DCE *ret; 00600 PLIST_ENTRY pLE; 00601 BOOL Hit = FALSE; 00602 00603 if (NULL == pdce) return NULL; 00604 00605 pLE = pdce->List.Flink; 00606 ret = CONTAINING_RECORD(pLE, DCE, List); 00607 00608 pdce->DCXFlags |= DCX_INDESTROY; 00609 00610 if (Force && 00611 GreGetObjectOwner(pdce->hDC) != GDI_OBJ_HMGR_POWNED) 00612 { 00613 TRACE("Change ownership for DCE! -> %x\n" , pdce); 00614 // NOTE: Windows sets W32PF_OWNDCCLEANUP and moves on. 00615 if (GreIsHandleValid(pdce->hDC)) 00616 { 00617 GreSetDCOwner(pdce->hDC, GDI_OBJ_HMGR_POWNED); 00618 } 00619 else 00620 { 00621 ERR("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce->hDC); 00622 Hit = TRUE; 00623 } 00624 } 00625 else 00626 { 00627 if (GreGetObjectOwner(pdce->hDC) == GDI_OBJ_HMGR_PUBLIC) 00628 GreSetDCOwner(pdce->hDC, GDI_OBJ_HMGR_POWNED); 00629 } 00630 00631 if (!Hit) IntGdiDeleteDC(pdce->hDC, TRUE); 00632 00633 if (pdce->hrgnClip && !(pdce->DCXFlags & DCX_KEEPCLIPRGN)) 00634 { 00635 GreDeleteObject(pdce->hrgnClip); 00636 pdce->hrgnClip = NULL; 00637 } 00638 00639 RemoveEntryList(&pdce->List); 00640 00641 if (IsListEmpty(&pdce->List)) 00642 { 00643 ERR("List is Empty! DCE! -> %x\n" , pdce); 00644 return NULL; 00645 } 00646 00647 ExFreePoolWithTag(pdce, USERTAG_DCE); 00648 00649 DCECount--; 00650 TRACE("Freed DCE's! %d \n", DCECount); 00651 00652 return ret; 00653 } 00654 00655 /*********************************************************************** 00656 * DceFreeWindowDCE 00657 * 00658 * Remove owned DCE and reset unreleased cache DCEs. 00659 */ 00660 void FASTCALL 00661 DceFreeWindowDCE(PWND Window) 00662 { 00663 PDCE pDCE; 00664 PLIST_ENTRY pLE; 00665 00666 if (DCECount <= 0) 00667 { 00668 ERR("FreeWindowDCE No Entry! %d\n",DCECount); 00669 return; 00670 } 00671 00672 pLE = LEDce.Flink; 00673 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00674 do 00675 { 00676 if (!pDCE) 00677 { 00678 ERR("FreeWindowDCE No DCE Pointer!\n"); 00679 break; 00680 } 00681 if (IsListEmpty(&pDCE->List)) 00682 { 00683 ERR("FreeWindowDCE List is Empty!!!!\n"); 00684 break; 00685 } 00686 if ( pDCE->hwndCurrent == Window->head.h && 00687 !(pDCE->DCXFlags & DCX_DCEEMPTY) ) 00688 { 00689 if (!(pDCE->DCXFlags & DCX_CACHE)) /* Owned or Class DCE */ 00690 { 00691 if (Window->pcls->style & CS_CLASSDC) /* Test Class first */ 00692 { 00693 if (pDCE->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) /* Class DCE */ 00694 DceDeleteClipRgn(pDCE); 00695 // Update and reset Vis Rgn and clear the dirty bit. 00696 // Should release VisRgn than reset it to default. 00697 DceUpdateVisRgn(pDCE, Window, pDCE->DCXFlags); 00698 pDCE->DCXFlags = DCX_DCEEMPTY|DCX_CACHE; 00699 pDCE->hwndCurrent = 0; 00700 00701 TRACE("POWNED DCE going Cheap!! DCX_CACHE!! hDC-> %x \n", pDCE->hDC); 00702 if (!GreSetDCOwner( pDCE->hDC, GDI_OBJ_HMGR_NONE)) 00703 { 00704 ERR("Fail Owner Switch hDC-> %x \n", pDCE->hDC); 00705 break; 00706 } 00707 /* Do not change owner so thread can clean up! */ 00708 } 00709 else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */ 00710 { 00711 pDCE = DceFreeDCE(pDCE, FALSE); 00712 if (!pDCE) break; 00713 continue; 00714 } 00715 else 00716 { 00717 ERR("Not POWNED or CLASSDC hwndCurrent -> %x \n", pDCE->hwndCurrent); 00718 // ASSERT(FALSE); /* bug 5320 */ 00719 } 00720 } 00721 else 00722 { 00723 if (pDCE->DCXFlags & DCX_DCEBUSY) /* Shared cache DCE */ 00724 { 00725 /* FIXME: AFAICS we are doing the right thing here so 00726 * this should be a TRACE. But this is best left as an ERR 00727 * because the 'application error' is likely to come from 00728 * another part of Wine (i.e. it's our fault after all). 00729 * We should change this to TRACE when ReactOS is more stable 00730 * (for 1.0?). 00731 */ 00732 ERR("[%p] GetDC() without ReleaseDC()!\n", Window->head.h); 00733 DceReleaseDC(pDCE, FALSE); 00734 } 00735 pDCE->DCXFlags |= DCX_DCEEMPTY; 00736 pDCE->hwndCurrent = 0; 00737 } 00738 } 00739 pLE = pDCE->List.Flink; 00740 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00741 } 00742 while (pLE != &LEDce); 00743 } 00744 00745 void FASTCALL 00746 DceFreeClassDCE(HDC hDC) 00747 { 00748 PDCE pDCE; 00749 PLIST_ENTRY pLE; 00750 pLE = LEDce.Flink; 00751 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00752 00753 do 00754 { 00755 if(!pDCE) break; 00756 if (pDCE->hDC == hDC) 00757 { 00758 pDCE = DceFreeDCE(pDCE, TRUE); // Might have gone cheap! 00759 if (!pDCE) break; 00760 continue; 00761 } 00762 pLE = pDCE->List.Flink; 00763 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00764 } 00765 while (pLE != &LEDce); 00766 } 00767 00768 void FASTCALL 00769 DceFreeThreadDCE(PTHREADINFO pti) 00770 { 00771 PDCE pDCE; 00772 PLIST_ENTRY pLE; 00773 pLE = LEDce.Flink; 00774 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00775 00776 do 00777 { 00778 if(!pDCE) break; 00779 if (pDCE->ptiOwner == pti) 00780 { 00781 if (pDCE->DCXFlags & DCX_CACHE) 00782 { 00783 pDCE = DceFreeDCE(pDCE, TRUE); 00784 if (!pDCE) break; 00785 continue; 00786 } 00787 } 00788 pLE = pDCE->List.Flink; 00789 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00790 } 00791 while (pLE != &LEDce); 00792 } 00793 00794 VOID FASTCALL 00795 DceEmptyCache(VOID) 00796 { 00797 PDCE pDCE; 00798 PLIST_ENTRY pLE; 00799 pLE = LEDce.Flink; 00800 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00801 00802 do 00803 { 00804 if(!pDCE) break; 00805 pDCE = DceFreeDCE(pDCE, TRUE); 00806 if(!pDCE) break; 00807 } 00808 while (pLE != &LEDce); 00809 } 00810 00811 VOID FASTCALL 00812 DceResetActiveDCEs(PWND Window) 00813 { 00814 DCE *pDCE; 00815 PDC dc; 00816 PWND CurrentWindow; 00817 INT DeltaX; 00818 INT DeltaY; 00819 PLIST_ENTRY pLE; 00820 00821 if (NULL == Window) 00822 { 00823 return; 00824 } 00825 pLE = LEDce.Flink; 00826 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00827 00828 do 00829 { 00830 if(!pDCE) break; 00831 if(pLE == &LEDce) break; 00832 if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY))) 00833 { 00834 if (Window->head.h == pDCE->hwndCurrent) 00835 { 00836 CurrentWindow = Window; 00837 } 00838 else 00839 { 00840 CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent); 00841 if (NULL == CurrentWindow) 00842 { 00843 pLE = pDCE->List.Flink; 00844 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00845 continue; 00846 } 00847 } 00848 00849 if (!GreIsHandleValid(pDCE->hDC) || 00850 (dc = DC_LockDc(pDCE->hDC)) == NULL) 00851 { 00852 pLE = pDCE->List.Flink; 00853 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00854 continue; 00855 } 00856 if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow)) 00857 { 00858 if (pDCE->DCXFlags & DCX_WINDOW) 00859 { 00860 DeltaX = CurrentWindow->rcWindow.left - dc->ptlDCOrig.x; 00861 DeltaY = CurrentWindow->rcWindow.top - dc->ptlDCOrig.y; 00862 dc->ptlDCOrig.x = CurrentWindow->rcWindow.left; 00863 dc->ptlDCOrig.y = CurrentWindow->rcWindow.top; 00864 } 00865 else 00866 { 00867 DeltaX = CurrentWindow->rcClient.left - dc->ptlDCOrig.x; 00868 DeltaY = CurrentWindow->rcClient.top - dc->ptlDCOrig.y; 00869 dc->ptlDCOrig.x = CurrentWindow->rcClient.left; 00870 dc->ptlDCOrig.y = CurrentWindow->rcClient.top; 00871 } 00872 if (NULL != dc->rosdc.hClipRgn) 00873 { 00874 NtGdiOffsetRgn(dc->rosdc.hClipRgn, DeltaX, DeltaY); 00875 CLIPPING_UpdateGCRegion(dc); 00876 } 00877 if (NULL != pDCE->hrgnClip) 00878 { 00879 NtGdiOffsetRgn(pDCE->hrgnClip, DeltaX, DeltaY); 00880 } 00881 } 00882 DC_UnlockDc(dc); 00883 00884 DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags); 00885 00886 if (Window->head.h != pDCE->hwndCurrent) 00887 { 00888 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT); 00889 // UserDerefObject(CurrentWindow); 00890 } 00891 } 00892 pLE = pDCE->List.Flink; 00893 pDCE = CONTAINING_RECORD(pLE, DCE, List); 00894 } 00895 while (pLE != &LEDce); 00896 } 00897 00898 HWND FASTCALL 00899 IntWindowFromDC(HDC hDc) 00900 { 00901 DCE *Dce; 00902 PLIST_ENTRY pLE; 00903 HWND Ret = NULL; 00904 00905 pLE = LEDce.Flink; 00906 Dce = CONTAINING_RECORD(pLE, DCE, List); 00907 do 00908 { 00909 if (Dce->hDC == hDc) 00910 { 00911 if (Dce->DCXFlags & DCX_INDESTROY) 00912 Ret = NULL; 00913 else 00914 Ret = Dce->hwndCurrent; 00915 break; 00916 } 00917 pLE = Dce->List.Flink; 00918 Dce = CONTAINING_RECORD(pLE, DCE, List); 00919 } 00920 while (pLE != &LEDce); 00921 return Ret; 00922 } 00923 00924 INT FASTCALL 00925 UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint) 00926 { 00927 PDCE dce; 00928 PLIST_ENTRY pLE; 00929 INT nRet = 0; 00930 BOOL Hit = FALSE; 00931 00932 TRACE("%p %p\n", Window, hDc); 00933 pLE = LEDce.Flink; 00934 dce = CONTAINING_RECORD(pLE, DCE, List); 00935 do 00936 { 00937 if(!dce) break; 00938 if (dce->hDC == hDc) 00939 { 00940 Hit = TRUE; 00941 break; 00942 } 00943 pLE = dce->List.Flink; 00944 dce = CONTAINING_RECORD(pLE, DCE, List); 00945 } 00946 while (pLE != &LEDce ); 00947 00948 if ( Hit && (dce->DCXFlags & DCX_DCEBUSY)) 00949 { 00950 nRet = DceReleaseDC(dce, EndPaint); 00951 } 00952 00953 return nRet; 00954 } 00955 00956 HDC FASTCALL 00957 UserGetWindowDC(PWND Wnd) 00958 { 00959 return UserGetDCEx(Wnd, 0, DCX_USESTYLE | DCX_WINDOW); 00960 } 00961 00962 HWND FASTCALL 00963 UserGethWnd( HDC hdc, PWNDOBJ *pwndo) 00964 { 00965 PWNDGDI pWndgdi; 00966 PWND Wnd; 00967 HWND hWnd; 00968 PPROPERTY pprop; 00969 00970 hWnd = IntWindowFromDC(hdc); 00971 00972 if (hWnd && !(Wnd = UserGetWindowObject(hWnd))) 00973 { 00974 pprop = IntGetProp(Wnd, AtomWndObj); 00975 00976 pWndgdi = (WNDGDI *)pprop->Data; 00977 00978 if ( pWndgdi && pWndgdi->Hwnd == hWnd ) 00979 { 00980 if (pwndo) *pwndo = (PWNDOBJ)pWndgdi; 00981 } 00982 } 00983 return hWnd; 00984 } 00985 00986 HDC APIENTRY 00987 NtUserGetDCEx(HWND hWnd OPTIONAL, HANDLE ClipRegion, ULONG Flags) 00988 { 00989 PWND Wnd=NULL; 00990 DECLARE_RETURN(HDC); 00991 00992 TRACE("Enter NtUserGetDCEx\n"); 00993 UserEnterExclusive(); 00994 00995 if (hWnd && !(Wnd = UserGetWindowObject(hWnd))) 00996 { 00997 RETURN(NULL); 00998 } 00999 RETURN( UserGetDCEx(Wnd, ClipRegion, Flags)); 01000 01001 CLEANUP: 01002 TRACE("Leave NtUserGetDCEx, ret=%i\n",_ret_); 01003 UserLeave(); 01004 END_CLEANUP; 01005 } 01006 01007 /* 01008 * NtUserGetWindowDC 01009 * 01010 * The NtUserGetWindowDC function retrieves the device context (DC) for the 01011 * entire window, including title bar, menus, and scroll bars. A window device 01012 * context permits painting anywhere in a window, because the origin of the 01013 * device context is the upper-left corner of the window instead of the client 01014 * area. 01015 * 01016 * Status 01017 * @implemented 01018 */ 01019 HDC APIENTRY 01020 NtUserGetWindowDC(HWND hWnd) 01021 { 01022 return NtUserGetDCEx(hWnd, 0, DCX_USESTYLE | DCX_WINDOW); 01023 } 01024 01025 HDC APIENTRY 01026 NtUserGetDC(HWND hWnd) 01027 { 01028 TRACE("NtUGetDC -> %x:%x\n", hWnd, !hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE ); 01029 01030 return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE); 01031 } 01032 01044 HPALETTE 01045 APIENTRY 01046 NtUserSelectPalette(HDC hDC, 01047 HPALETTE hpal, 01048 BOOL ForceBackground) 01049 { 01050 HPALETTE oldPal; 01051 UserEnterExclusive(); 01052 // Implement window checks 01053 oldPal = GdiSelectPalette( hDC, hpal, ForceBackground); 01054 UserLeave(); 01055 return oldPal; 01056 } 01057 01058 /* EOF */ Generated on Sun May 27 2012 04:38:36 for ReactOS by
1.7.6.1
|