/* UserUpdateMonitorSize * * Reset size of the monitor using atached device * * Arguments * * PMONITOR * pGdiDevice Pointer to the PDEVOBJ, which size has changed * * Return value * Returns a NTSTATUS */ NTSTATUS NTAPI UserUpdateMonitorSize(IN HDEV hDev) { PMONITOR pMonitor; SIZEL DeviceSize; /* Find monitor attached to given device */ for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) { if (pMonitor->hDev == hDev) break; } if (pMonitor == NULL) { /* No monitor has been found */ return STATUS_INVALID_PARAMETER; } /* Get the size of the hdev */ PDEVOBJ_sizl((PPDEVOBJ)hDev, &DeviceSize); /* Update monitor size */ pMonitor->rcMonitor.left = 0; pMonitor->rcMonitor.top = 0; pMonitor->rcMonitor.right = pMonitor->rcMonitor.left + DeviceSize.cx; pMonitor->rcMonitor.bottom = pMonitor->rcMonitor.top + DeviceSize.cy; pMonitor->rcWork = pMonitor->rcMonitor; /* Destroy monitor region... */ if (pMonitor->hrgnMonitor) { GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(pMonitor->hrgnMonitor); } /* ...and create new one */ pMonitor->hrgnMonitor = NtGdiCreateRectRgn( pMonitor->rcMonitor.left, pMonitor->rcMonitor.top, pMonitor->rcMonitor.right, pMonitor->rcMonitor.bottom); if (pMonitor->hrgnMonitor) IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC); return STATUS_SUCCESS; }
static void DC_vUpdateDC(PDC pdc) { HRGN hVisRgn ; PPDEVOBJ ppdev = pdc->ppdev ; pdc->dhpdev = ppdev->dhpdev; SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface); pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev); PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl); hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy); ASSERT(hVisRgn); GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn); GreDeleteObject(hVisRgn); pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps; pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2; /* Mark EBRUSHOBJs as dirty */ pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ; }
/* * @implemented */ HRGN WINAPI CreateRectRgn(int x1, int y1, int x2, int y2) { PRGN_ATTR pRgn_Attr; HRGN hrgn; int tmp; /// <- //// Remove when Brush/Pen/Rgn Attr is ready! return NtGdiCreateRectRgn(x1,y1,x2,y2); //// /* Normalize points */ tmp = x1; if ( x1 > x2 ) { x1 = x2; x2 = tmp; } tmp = y1; if ( y1 > y2 ) { y1 = y2; y2 = tmp; } /* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/ if ( x1 < -(1<<27) || y1 < -(1<<27) || x2 > (1<<27)-1 || y2 > (1<<27)-1 ) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } hrgn = hGetPEBHandle(hctRegionHandle, 0); if (!hrgn) hrgn = NtGdiCreateRectRgn(0, 0, 1, 1); if (!hrgn) return hrgn; if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr)) { DPRINT1("No Attr for Region handle!!!\n"); DeleteRegion(hrgn); return NULL; } if (( x1 == x2) || (y1 == y2)) { pRgn_Attr->iComplexity = NULLREGION; pRgn_Attr->Rect.left = pRgn_Attr->Rect.top = pRgn_Attr->Rect.right = pRgn_Attr->Rect.bottom = 0; } else { pRgn_Attr->iComplexity = SIMPLEREGION; pRgn_Attr->Rect.left = x1; pRgn_Attr->Rect.top = y1; pRgn_Attr->Rect.right = x2; pRgn_Attr->Rect.bottom = y2; } pRgn_Attr->AttrFlags = (ATTR_RGN_DIRTY|ATTR_RGN_VALID); return hrgn; }
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); }