BOOL FASTCALL co_IntInitializeDesktopGraphics(VOID) { TEXTMETRICW tmw; UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY"); PDESKTOP pdesk; ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE); if (NULL == ScreenDeviceContext) { IntDestroyPrimarySurface(); return FALSE; } GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC); if (! IntCreatePrimarySurface()) { return FALSE; } hSystemBM = NtGdiCreateCompatibleDC(ScreenDeviceContext); NtGdiSelectFont(hSystemBM, NtGdiGetStockObject(SYSTEM_FONT)); GreSetDCOwner(hSystemBM, GDI_OBJ_HMGR_PUBLIC); /* Update the SERVERINFO */ gpsi->aiSysMet[SM_CXSCREEN] = gppdevPrimary->gdiinfo.ulHorzRes; gpsi->aiSysMet[SM_CYSCREEN] = gppdevPrimary->gdiinfo.ulVertRes; gpsi->Planes = NtGdiGetDeviceCaps(ScreenDeviceContext, PLANES); gpsi->BitsPixel = NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL); gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel; gpsi->dmLogPixels = NtGdiGetDeviceCaps(ScreenDeviceContext, LOGPIXELSY); if (NtGdiGetDeviceCaps(ScreenDeviceContext, RASTERCAPS) & RC_PALETTE) { gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY; } else gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY; // Font is realized and this dc was previously set to internal DC_ATTR. gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar); gpsi->tmSysFont = tmw; /* Put the pointer in the center of the screen */ gpsi->ptCursor.x = gpsi->aiSysMet[SM_CXSCREEN] / 2; gpsi->ptCursor.y = gpsi->aiSysMet[SM_CYSCREEN] / 2; /* Attach monitor */ UserAttachMonitor((HDEV)gppdevPrimary); /* Setup the cursor */ co_IntLoadDefaultCursors(); /* Show the desktop */ pdesk = IntGetActiveDesktop(); ASSERT(pdesk); co_IntShowDesktop(pdesk, gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN], TRUE); return TRUE; }
/*********************************************************************** * DceFreeDCE */ void FASTCALL DceFreeDCE(PDCE pdce, BOOLEAN Force) { BOOL Hit = FALSE; ASSERT(pdce != NULL); if (NULL == pdce) return; pdce->DCXFlags |= DCX_INDESTROY; if (Force && GreGetObjectOwner(pdce->hDC) != GDI_OBJ_HMGR_POWNED) { TRACE("Change ownership for DCE! -> %p\n" , pdce); // NOTE: Windows sets W32PF_OWNDCCLEANUP and moves on. if (GreIsHandleValid(pdce->hDC)) { GreSetDCOwner(pdce->hDC, GDI_OBJ_HMGR_POWNED); } else { ERR("Attempted to change ownership of an DCEhDC %p currently being destroyed!!!\n", pdce->hDC); Hit = TRUE; } } else { if (GreGetObjectOwner(pdce->hDC) == GDI_OBJ_HMGR_PUBLIC) GreSetDCOwner(pdce->hDC, GDI_OBJ_HMGR_POWNED); } if (!Hit) IntGdiDeleteDC(pdce->hDC, TRUE); if (pdce->hrgnClip && !(pdce->DCXFlags & DCX_KEEPCLIPRGN)) { GreDeleteObject(pdce->hrgnClip); pdce->hrgnClip = NULL; } RemoveEntryList(&pdce->List); ExFreePoolWithTag(pdce, USERTAG_DCE); DCECount--; TRACE("Freed DCE's! %d \n", DCECount); }
PDCE FASTCALL DceAllocDCE(PWND Window OPTIONAL, DCE_TYPE Type) { PDCE pDce; pDce = ExAllocatePoolWithTag(PagedPool, sizeof(DCE), USERTAG_DCE); if(!pDce) return NULL; pDce->hDC = DceCreateDisplayDC(); if (!pDce->hDC) { ExFreePoolWithTag(pDce, USERTAG_DCE); return NULL; } DCECount++; TRACE("Alloc DCE's! %d\n",DCECount); pDce->hwndCurrent = (Window ? Window->head.h : NULL); pDce->pwndOrg = Window; pDce->pwndClip = Window; pDce->hrgnClip = NULL; pDce->hrgnClipPublic = NULL; pDce->hrgnSavedVis = NULL; pDce->ppiOwner = NULL; InsertTailList(&LEDce, &pDce->List); DCU_SetDcUndeletable(pDce->hDC); if (Type == DCE_WINDOW_DC || Type == DCE_CLASS_DC) // Window DCE have ownership. { pDce->ptiOwner = GetW32ThreadInfo(); } else { TRACE("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %p\n", pDce->hDC); GreSetDCOwner(pDce->hDC, GDI_OBJ_HMGR_NONE); pDce->ptiOwner = NULL; } if (Type == DCE_CACHE_DC) { pDce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY; } else { pDce->DCXFlags = DCX_DCEBUSY; if (Window) { if (Type == DCE_WINDOW_DC) { if (Window->style & WS_CLIPCHILDREN) pDce->DCXFlags |= DCX_CLIPCHILDREN; if (Window->style & WS_CLIPSIBLINGS) pDce->DCXFlags |= DCX_CLIPSIBLINGS; } } } return(pDce); }
void CleanupTooltipAnimation(PTOOLTIPWND pttwnd) { DestroyTooltipBitmap(pttwnd); if (pttwnd->hdcMem != NULL) { GreSetDCOwner(pttwnd->hdcMem, OBJECT_OWNER_CURRENT); GreDeleteDC(pttwnd->hdcMem); } }
void InitTooltipAnimation(PTOOLTIPWND pttwnd) { HDC hdc = GetTooltipDC(pttwnd); if ((pttwnd->hdcMem = GreCreateCompatibleDC(hdc)) == NULL) { return; } _ReleaseDC(hdc); GreSetDCOwner(pttwnd->hdcMem, OBJECT_OWNER_PUBLIC); }
VOID FASTCALL IntEndDesktopGraphics(VOID) { if (NULL != ScreenDeviceContext) { // No need to allocate a new dcattr. GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_POWNED); GreDeleteObject(ScreenDeviceContext); ScreenDeviceContext = NULL; } IntHideDesktop(IntGetActiveDesktop()); IntDestroyPrimarySurface(); }
BOOL xxxSendEraseBkgnd( PWND pwnd, HDC hdcBeginPaint, HRGN hrgnUpdate) { PTHREADINFO ptiCurrent; BOOL fErased; HDC hdc; CheckLock(pwnd); /* * For minimized dudes in win3.1, we would've sent an * WM_ICONERASEBKGND and cleared the erase bit. Now that min * windows in 4.0 are all nonclient, don't bother erasing at * all. Pretend like we did. * * NOTE: * For < 4.0 windows, we may have to send a fake WM_ICONERASEKBGND * to keep 'em happy. Saves time not to though. Getting a DC and * sending the message ain't speedy. */ if ((hrgnUpdate == NULL) || TestWF(pwnd, WFMINIMIZED)) return FALSE; /* * If a DC to use was not passed in, get one. * We want one clipped to this window's update region. */ if (hdcBeginPaint == NULL) { hdc = _GetDCEx(pwnd, hrgnUpdate, DCX_USESTYLE | DCX_INTERSECTRGN | DCX_NODELETERGN); } else { hdc = hdcBeginPaint; } /* * If we're send the WM_ERASEBKGND to another process * we need to change the DC owner. * * We'd like to change the owner to pwnd->pti->idProcess, but * GDI won't let us assign ownership back to ourselves later. */ ptiCurrent = PtiCurrent(); if (GETPTI(pwnd)->ppi != ptiCurrent->ppi) GreSetDCOwner(hdc, OBJECT_OWNER_PUBLIC); /* * Send the event to the window. This contains the DC clipped to * the update-region. */ fErased = (BOOL)xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L); /* * If we've changed the DC owner, change it back to * the current process. */ if (GETPTI(pwnd)->ppi != ptiCurrent->ppi) GreSetDCOwner(hdc, OBJECT_OWNER_CURRENT); /* * If the WM_ERASEBKGND message did not erase the * background, then set this flag to let BeginPaint() * know to ask the caller to do it via the fErase * flag in the PAINTSTRUCT. */ if (!fErased) { SetWF(pwnd, WFERASEBKGND); if (!TestWF(pwnd, WFWIN31COMPAT)) SetWF(pwnd, WFSENDERASEBKGND); } /* * If we got a cache DC in this routine, release it. */ if (hdcBeginPaint == NULL) { ReleaseCacheDC(hdc, TRUE); } return fErased; }
/*********************************************************************** * DceFreeWindowDCE * * Remove owned DCE and reset unreleased cache DCEs. */ void FASTCALL DceFreeWindowDCE(PWND Window) { PDCE pDCE; PLIST_ENTRY ListEntry; if (DCECount <= 0) { ERR("FreeWindowDCE No Entry! %d\n",DCECount); return; } ListEntry = LEDce.Flink; while (ListEntry != &LEDce) { pDCE = CONTAINING_RECORD(ListEntry, DCE, List); ListEntry = ListEntry->Flink; if ( pDCE->hwndCurrent == Window->head.h && !(pDCE->DCXFlags & DCX_DCEEMPTY) ) { if (!(pDCE->DCXFlags & DCX_CACHE)) /* Owned or Class DCE */ { if (Window->pcls->style & CS_CLASSDC) /* Test Class first */ { if (pDCE->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) /* Class DCE */ DceDeleteClipRgn(pDCE); // Update and reset Vis Rgn and clear the dirty bit. // Should release VisRgn than reset it to default. DceUpdateVisRgn(pDCE, Window, pDCE->DCXFlags); pDCE->DCXFlags = DCX_DCEEMPTY|DCX_CACHE; pDCE->hwndCurrent = 0; pDCE->pwndOrg = pDCE->pwndClip = NULL; TRACE("POWNED DCE going Cheap!! DCX_CACHE!! hDC-> %p \n", pDCE->hDC); if (!GreSetDCOwner( pDCE->hDC, GDI_OBJ_HMGR_NONE)) { ERR("Fail Owner Switch hDC-> %p \n", pDCE->hDC); break; } /* Do not change owner so thread can clean up! */ } else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */ { DceFreeDCE(pDCE, FALSE); continue; } else { ERR("Not POWNED or CLASSDC hwndCurrent -> %p \n", pDCE->hwndCurrent); // ASSERT(FALSE); /* bug 5320 */ } } else { if (pDCE->DCXFlags & DCX_DCEBUSY) /* Shared cache DCE */ { /* FIXME: AFAICS we are doing the right thing here so * this should be a TRACE. But this is best left as an ERR * because the 'application error' is likely to come from * another part of Wine (i.e. it's our fault after all). * We should change this to TRACE when ReactOS is more stable * (for 1.0?). */ ERR("[%p] GetDC() without ReleaseDC()!\n", Window->head.h); DceReleaseDC(pDCE, FALSE); } pDCE->DCXFlags |= DCX_DCEEMPTY; pDCE->hwndCurrent = 0; pDCE->pwndOrg = pDCE->pwndClip = NULL; } } } }
HDC FASTCALL UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags) { PWND Parent; ULONG DcxFlags; DCE* Dce = NULL; BOOL UpdateClipOrigin = FALSE; BOOL bUpdateVisRgn = TRUE; HDC hDC = NULL; PPROCESSINFO ppi; PLIST_ENTRY ListEntry; if (NULL == Wnd) { Flags &= ~DCX_USESTYLE; Flags |= DCX_CACHE; } if (Flags & DCX_PARENTCLIP) Flags |= DCX_CACHE; // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set. if (Flags & DCX_USESTYLE) { Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP); if (!(Flags & DCX_WINDOW)) // Not window rectangle { if (Wnd->pcls->style & CS_PARENTDC) { Flags |= DCX_PARENTCLIP; } if (!(Flags & DCX_CACHE) && // Not on the cheap wine list. !(Wnd->pcls->style & CS_OWNDC) ) { if (!(Wnd->pcls->style & CS_CLASSDC)) // The window is not POWNED or has any CLASS, so we are looking for cheap wine. Flags |= DCX_CACHE; else { if (Wnd->pcls->pdce) hDC = ((PDCE)Wnd->pcls->pdce)->hDC; TRACE("We have CLASS!!\n"); } } if (Wnd->style & WS_CLIPSIBLINGS) { Flags |= DCX_CLIPSIBLINGS; } if (Wnd->style & WS_CLIPCHILDREN && !(Wnd->style & WS_MINIMIZE)) { Flags |= DCX_CLIPCHILDREN; } /* If minized with icon in the set, we are forced to be cheap! */ if (Wnd->style & WS_MINIMIZE && Wnd->pcls->spicn) { Flags |= DCX_CACHE; } } else { if (Wnd->style & WS_CLIPSIBLINGS) Flags |= DCX_CLIPSIBLINGS; Flags |= DCX_CACHE; } } if (Flags & DCX_WINDOW) Flags &= ~DCX_CLIPCHILDREN; if (Flags & DCX_NOCLIPCHILDREN) { Flags |= DCX_CACHE; Flags &= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN); } Parent = (Wnd ? Wnd->spwndParent : NULL); if (NULL == Wnd || !(Wnd->style & WS_CHILD) || NULL == Parent) { Flags &= ~DCX_PARENTCLIP; Flags |= DCX_CLIPSIBLINGS; } /* It seems parent clip is ignored when clipping siblings or children */ if (Flags & (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN)) Flags &= ~DCX_PARENTCLIP; if (Flags & DCX_PARENTCLIP) { if ((Wnd->style & WS_VISIBLE) && (Parent->style & WS_VISIBLE)) { Flags &= ~DCX_CLIPCHILDREN; if (Parent->style & WS_CLIPSIBLINGS) { Flags |= DCX_CLIPSIBLINGS; } } } // Window nz, check to see if we still own this or it is just cheap wine tonight. if (!(Flags & DCX_CACHE)) { if ( Wnd->head.pti != GetW32ThreadInfo()) Flags |= DCX_CACHE; // Ah~ Not Powned! Forced to be cheap~ } DcxFlags = Flags & DCX_CACHECOMPAREMASK; if (Flags & DCX_CACHE) { // Scan the cheap wine list for our match. DCE* DceEmpty = NULL; DCE* DceUnused = NULL; KeEnterCriticalRegion(); ListEntry = LEDce.Flink; while (ListEntry != &LEDce) { Dce = CONTAINING_RECORD(ListEntry, DCE, List); ListEntry = ListEntry->Flink; // // The way I understand this, you can have more than one DC per window. // Only one Owned if one was requested and saved and one Cached. // if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE) { DceUnused = Dce; if (Dce->DCXFlags & DCX_DCEEMPTY) { DceEmpty = Dce; } else if (Dce->hwndCurrent == (Wnd ? Wnd->head.h : NULL) && ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags)) { UpdateClipOrigin = TRUE; break; } } Dce = NULL; // Loop issue? } KeLeaveCriticalRegion(); Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty; if (Dce == NULL) { Dce = DceAllocDCE(NULL, DCE_CACHE_DC); } if (Dce == NULL) return NULL; Dce->hwndCurrent = (Wnd ? Wnd->head.h : NULL); Dce->pwndOrg = Dce->pwndClip = Wnd; } else // If we are here, we are POWNED or having CLASS. { KeEnterCriticalRegion(); ListEntry = LEDce.Flink; while (ListEntry != &LEDce) { Dce = CONTAINING_RECORD(ListEntry, DCE, List); ListEntry = ListEntry->Flink; // Skip Cache DCE entries. if (!(Dce->DCXFlags & DCX_CACHE)) { // Check for Window handle than HDC match for CLASS. if (Dce->hwndCurrent == Wnd->head.h) { bUpdateVisRgn = FALSE; break; } else if (Dce->hDC == hDC) break; } Dce = NULL; // Loop issue? } KeLeaveCriticalRegion(); if (Dce == NULL) { return(NULL); } if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) && (Dce->DCXFlags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) ) { DceDeleteClipRgn(Dce); } } // First time use hax, need to use DceAllocDCE during window display init. if (NULL == Dce) { return(NULL); } if (!GreIsHandleValid(Dce->hDC)) { ERR("FIXME: Got DCE with invalid hDC! %p\n", Dce->hDC); Dce->hDC = DceCreateDisplayDC(); /* FIXME: Handle error */ } Dce->DCXFlags = Flags | DCX_DCEBUSY; /* * Bump it up! This prevents the random errors in wine dce tests and with * proper bits set in DCX_CACHECOMPAREMASK. * Reference: * http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html * http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html */ RemoveEntryList(&Dce->List); InsertHeadList(&LEDce, &Dce->List); /* Introduced in rev 6691 and modified later. */ if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion ) { Flags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN; Dce->DCXFlags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN; ClipRegion = Wnd->hrgnUpdate; bUpdateVisRgn = TRUE; } if (ClipRegion == HRGN_WINDOW) { if (!(Flags & DCX_WINDOW)) { Dce->hrgnClip = NtGdiCreateRectRgn( Wnd->rcClient.left, Wnd->rcClient.top, Wnd->rcClient.right, Wnd->rcClient.bottom); } else { Dce->hrgnClip = NtGdiCreateRectRgn( Wnd->rcWindow.left, Wnd->rcWindow.top, Wnd->rcWindow.right, Wnd->rcWindow.bottom); } Dce->DCXFlags &= ~DCX_KEEPCLIPRGN; bUpdateVisRgn = TRUE; } else if (ClipRegion != NULL) { if (Dce->hrgnClip != NULL) { ERR("Should not be called!!\n"); GreDeleteObject(Dce->hrgnClip); Dce->hrgnClip = NULL; } Dce->hrgnClip = ClipRegion; bUpdateVisRgn = TRUE; } if (IntGdiSetHookFlags(Dce->hDC, DCHF_VALIDATEVISRGN)) bUpdateVisRgn = TRUE; DceSetDrawable(Wnd, Dce->hDC, Flags, UpdateClipOrigin); if (bUpdateVisRgn) DceUpdateVisRgn(Dce, Wnd, Flags); if (Dce->DCXFlags & DCX_CACHE) { TRACE("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %p\n", Dce->hDC); // Need to set ownership so Sync dcattr will work. GreSetDCOwner(Dce->hDC, GDI_OBJ_HMGR_POWNED); Dce->ptiOwner = GetW32ThreadInfo(); // Set the temp owning } if ( Wnd && Wnd->ExStyle & WS_EX_LAYOUTRTL && !(Flags & DCX_KEEPLAYOUT) ) { NtGdiSetLayout(Dce->hDC, -1, LAYOUT_RTL); } if (Dce->DCXFlags & DCX_PROCESSOWNED) { ppi = PsGetCurrentProcessWin32Process(); ppi->W32PF_flags |= W32PF_OWNDCCLEANUP; Dce->ptiOwner = NULL; Dce->ppiOwner = ppi; } return(Dce->hDC); }
static INT FASTCALL DceReleaseDC(DCE* dce, BOOL EndPaint) { if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_INDESTROY | DCX_DCEEMPTY | DCX_DCEBUSY))) { return 0; } /* Restore previous visible region */ if (EndPaint) { DceUpdateVisRgn(dce, dce->pwndOrg, dce->DCXFlags); } if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) && ((dce->DCXFlags & DCX_CACHE) || EndPaint)) { DceDeleteClipRgn(dce); } if (dce->DCXFlags & DCX_CACHE) { if (!(dce->DCXFlags & DCX_NORESETATTRS)) { // Clean the DC if (!IntGdiCleanDC(dce->hDC)) return 0; if (dce->DCXFlags & DCX_DCEDIRTY) { /* Don't keep around invalidated entries * because SetDCState() disables hVisRgn updates * by removing dirty bit. */ dce->hwndCurrent = 0; dce->pwndOrg = NULL; dce->pwndClip = NULL; dce->DCXFlags &= DCX_CACHE; dce->DCXFlags |= DCX_DCEEMPTY; } } dce->DCXFlags &= ~DCX_DCEBUSY; TRACE("Exit!!!!! DCX_CACHE!!!!!! hDC-> %p \n", dce->hDC); if (!GreSetDCOwner(dce->hDC, GDI_OBJ_HMGR_NONE)) return 0; dce->ptiOwner = NULL; // Reset ownership. dce->ppiOwner = NULL; #if 0 // Need to research and fix before this is a "growing" issue. if (++DCECache > 32) { ListEntry = LEDce.Flink; while (ListEntry != &LEDce) { pDCE = CONTAINING_RECORD(ListEntry, DCE, List); ListEntry = ListEntry->Flink; if (!(pDCE->DCXFlags & DCX_DCEBUSY)) { /* Free the unused cache DCEs. */ DceFreeDCE(pDCE, TRUE); } } } #endif } return 1; // Released! }
BOOL APIENTRY DxEngSetDCOwner(HGDIOBJ hObject, DWORD OwnerMask) { DPRINT1("ReactX Calling : DxEngSetDCOwner \n"); return GreSetDCOwner(hObject, OwnerMask); }