/*
* PROJECT: ReactOS Win32k subsystem
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: subsystems/win32/win32k/ntuser/windc.c
+ * FILE: win32ss/user/ntuser/windc.c
* PURPOSE: Window DC management
* COPYRIGHT: Copyright 2007 ReactOS Team
*/
FASTCALL
DceGetDceFromDC(HDC hdc)
{
- LIST_ENTRY* Entry = LEDce.Flink;
+ PLIST_ENTRY ListEntry;
DCE* dce;
- while (Entry != &LEDce)
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- dce = CONTAINING_RECORD(Entry, DCE, List);
+ dce = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
if (dce->hDC == hdc)
return dce;
- Entry = Entry->Flink;
}
return NULL;
PREGION FASTCALL
DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
{
- PREGION RetRgn;
- HRGN hVisRgn;
- hVisRgn = VIS_ComputeVisibleRegion( Window,
- 0 == (Flags & DCX_WINDOW),
- 0 != (Flags & DCX_CLIPCHILDREN),
- 0 != (Flags & DCX_CLIPSIBLINGS));
-
- RetRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
-
- if (hVisRgn != NULL)
- {
- PREGION VisRgn = REGION_LockRgn(hVisRgn);
- IntGdiCombineRgn(RetRgn, VisRgn, NULL, RGN_COPY);
- REGION_UnlockRgn(VisRgn);
- GreDeleteObject(hVisRgn);
- }
-
- return RetRgn;
+ PREGION Rgn;
+ Rgn = VIS_ComputeVisibleRegion( Window,
+ 0 == (Flags & DCX_WINDOW),
+ 0 != (Flags & DCX_CLIPCHILDREN),
+ 0 != (Flags & DCX_CLIPSIBLINGS));
+ /* Caller expects a non-null region */
+ if (!Rgn)
+ Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
+ return Rgn;
}
PDCE FASTCALL
ULONG Flags,
BOOL SetClipOrigin)
{
- DC *dc = DC_LockDc(hDC);
- if(!dc)
- return;
+ RECTL rect;
- if (Window == NULL)
- {
- dc->ptlDCOrig.x = 0;
- dc->ptlDCOrig.y = 0;
- }
- else
+ if (Window)
{
if (Flags & DCX_WINDOW)
{
- dc->ptlDCOrig.x = Window->rcWindow.left;
- dc->ptlDCOrig.y = Window->rcWindow.top;
+ rect = Window->rcWindow;
}
else
{
- dc->ptlDCOrig.x = Window->rcClient.left;
- dc->ptlDCOrig.y = Window->rcClient.top;
+ rect = Window->rcClient;
}
}
- dc->fs |= DC_FLAG_DIRTY_RAO;
- DC_UnlockDc(dc);
+
+ /* Set DC Origin and Window Rectangle */
+ GreSetDCOrg( hDC, rect.left, rect.top, &rect);
}
PWND Parent;
Parent = Window->spwndParent;
- if(!Parent)
+ if (!Parent)
{
RgnVisible = NULL;
goto noparent;
noparent:
if (Flags & DCX_INTERSECTRGN)
{
- if(Dce->hrgnClip != NULL)
+ PREGION RgnClip = NULL;
+
+ if (Dce->hrgnClip != NULL)
+ RgnClip = REGION_LockRgn(Dce->hrgnClip);
+
+ if (RgnClip)
{
- PREGION RgnClip = REGION_LockRgn(Dce->hrgnClip);
IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND);
REGION_UnlockRgn(RgnClip);
}
else
{
- if(RgnVisible != NULL)
+ if (RgnVisible != NULL)
{
REGION_Delete(RgnVisible);
}
#if 0 // Need to research and fix before this is a "growing" issue.
if (++DCECache > 32)
{
- pLE = LEDce.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
- do
+ 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. */
- pDCE = DceFreeDCE(pDCE, TRUE);
- if (!pDCE) break;
- continue;
+ DceFreeDCE(pDCE, TRUE);
}
}
- while (pLE != &LEDce );
}
#endif
}
BOOL bUpdateVisRgn = TRUE;
HDC hDC = NULL;
PPROCESSINFO ppi;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
if (NULL == Wnd)
{
Flags |= DCX_CACHE;
}
- if (Flags & (DCX_WINDOW | DCX_PARENTCLIP)) 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;
}
/* If minized with icon in the set, we are forced to be cheap! */
- if (Wnd->style & WS_MINIMIZE &&
- Wnd->pcls->hIcon)
+ if (Wnd->style & WS_MINIMIZE && Wnd->pcls->spicn)
{
Flags |= DCX_CACHE;
}
DCE* DceEmpty = NULL;
DCE* DceUnused = NULL;
KeEnterCriticalRegion();
- pLE = LEDce.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
-// The reason for this you may ask?
-// Well, it seems ReactOS calls GetDC without first creating a desktop DC window!
-// Need to test for null here. Not sure if this is a bug or a feature.
-// First time use hax, need to use DceAllocDCE during window display init.
- if (!Dce) break;
+ 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.
break;
}
}
- pLE = Dce->List.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
+ Dce = NULL; // Loop issue?
}
- while (pLE != &LEDce);
KeLeaveCriticalRegion();
Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
{
Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
}
- if (!Dce) return NULL;
+ 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();
- pLE = LEDce.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
- do
- { // Check for Window handle than HDC match for CLASS.
- if (Dce->hwndCurrent == Wnd->head.h)
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
+ {
+ Dce = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
+
+ // Skip Cache DCE entries.
+ if (!(Dce->DCXFlags & DCX_CACHE))
{
- bUpdateVisRgn = FALSE;
- break;
+ // Check for Window handle than HDC match for CLASS.
+ if (Dce->hwndCurrent == Wnd->head.h)
+ {
+ bUpdateVisRgn = FALSE;
+ break;
+ }
+ else if (Dce->hDC == hDC) break;
}
- if (Dce->hDC == hDC) break;
- pLE = Dce->List.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
+ Dce = NULL; // Loop issue?
}
- while (pLE != &LEDce);
KeLeaveCriticalRegion();
+ if (Dce == NULL)
+ {
+ return(NULL);
+ }
+
if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) &&
(Dce->DCXFlags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) )
{
- DceDeleteClipRgn(Dce);
+ DceDeleteClipRgn(Dce);
}
}
// First time use hax, need to use DceAllocDCE during window display init.
* http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html
* http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html
*/
- if (pLE != &LEDce)
- {
- RemoveEntryList(&Dce->List);
- InsertHeadList(&LEDce, &Dce->List);
- }
+ RemoveEntryList(&Dce->List);
+ InsertHeadList(&LEDce, &Dce->List);
/* Introduced in rev 6691 and modified later. */
if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion )
{
if (!(Flags & DCX_WINDOW))
{
- Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
+ Dce->hrgnClip = NtGdiCreateRectRgn(
+ Wnd->rcClient.left,
+ Wnd->rcClient.top,
+ Wnd->rcClient.right,
+ Wnd->rcClient.bottom);
}
else
{
- Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
+ Dce->hrgnClip = NtGdiCreateRectRgn(
+ Wnd->rcWindow.left,
+ Wnd->rcWindow.top,
+ Wnd->rcWindow.right,
+ Wnd->rcWindow.bottom);
}
Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
bUpdateVisRgn = TRUE;
/***********************************************************************
* DceFreeDCE
*/
-PDCE FASTCALL
+void FASTCALL
DceFreeDCE(PDCE pdce, BOOLEAN Force)
{
- DCE *ret;
- PLIST_ENTRY pLE;
BOOL Hit = FALSE;
- if (NULL == pdce) return NULL;
-
- pLE = pdce->List.Flink;
- ret = CONTAINING_RECORD(pLE, DCE, List);
+ ASSERT(pdce != NULL);
+ if (NULL == pdce) return;
pdce->DCXFlags |= DCX_INDESTROY;
RemoveEntryList(&pdce->List);
- if (IsListEmpty(&pdce->List))
- {
- ERR("List is Empty! DCE! -> %p\n" , pdce);
- return NULL;
- }
-
ExFreePoolWithTag(pdce, USERTAG_DCE);
DCECount--;
TRACE("Freed DCE's! %d \n", DCECount);
-
- return ret;
}
/***********************************************************************
DceFreeWindowDCE(PWND Window)
{
PDCE pDCE;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
if (DCECount <= 0)
{
return;
}
- pLE = LEDce.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- if (!pDCE)
- {
- ERR("FreeWindowDCE No DCE Pointer!\n");
- break;
- }
- if (IsListEmpty(&pDCE->List))
- {
- ERR("FreeWindowDCE List is Empty!!!!\n");
- break;
- }
+ pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
if ( pDCE->hwndCurrent == Window->head.h &&
!(pDCE->DCXFlags & DCX_DCEEMPTY) )
{
}
else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */
{
- pDCE = DceFreeDCE(pDCE, FALSE);
- if (!pDCE) break;
+ DceFreeDCE(pDCE, FALSE);
continue;
}
else
pDCE->pwndOrg = pDCE->pwndClip = NULL;
}
}
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
}
void FASTCALL
-DceFreeClassDCE(HDC hDC)
+DceFreeClassDCE(PDCE pdceClass)
{
PDCE pDCE;
- PLIST_ENTRY pLE;
- pLE = LEDce.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
+ PLIST_ENTRY ListEntry;
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- if(!pDCE) break;
- if (pDCE->hDC == hDC)
+ pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
+ if (pDCE == pdceClass)
{
- pDCE = DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
- if (!pDCE) break;
- continue;
+ DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
}
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
}
void FASTCALL
DceFreeThreadDCE(PTHREADINFO pti)
{
PDCE pDCE;
- PLIST_ENTRY pLE;
- pLE = LEDce.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
+ PLIST_ENTRY ListEntry;
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- if(!pDCE) break;
+ pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
if (pDCE->ptiOwner == pti)
{
if (pDCE->DCXFlags & DCX_CACHE)
{
- pDCE = DceFreeDCE(pDCE, TRUE);
- if (!pDCE) break;
- continue;
+ DceFreeDCE(pDCE, TRUE);
}
}
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
}
VOID FASTCALL
DceEmptyCache(VOID)
{
PDCE pDCE;
- PLIST_ENTRY pLE;
- pLE = LEDce.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
+ PLIST_ENTRY ListEntry;
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- if(!pDCE) break;
- pDCE = DceFreeDCE(pDCE, TRUE);
- if(!pDCE) break;
+ pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
+ DceFreeDCE(pDCE, TRUE);
}
- while (pLE != &LEDce);
}
VOID FASTCALL
PWND CurrentWindow;
INT DeltaX;
INT DeltaY;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
if (NULL == Window)
{
return;
}
- pLE = LEDce.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- if(!pDCE) break;
- if(pLE == &LEDce) break;
+ pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY)))
{
if (Window->head.h == pDCE->hwndCurrent)
CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
if (NULL == CurrentWindow)
{
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
continue;
}
}
if (!GreIsHandleValid(pDCE->hDC) ||
(dc = DC_LockDc(pDCE->hDC)) == NULL)
{
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
continue;
}
if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow))
if (NULL != dc->dclevel.prgnClip)
{
- IntGdiOffsetRgn(dc->dclevel.prgnClip, DeltaX, DeltaY);
+ REGION_bOffsetRgn(dc->dclevel.prgnClip, DeltaX, DeltaY);
dc->fs |= DC_FLAG_DIRTY_RAO;
}
if (NULL != pDCE->hrgnClip)
DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
IntGdiSetHookFlags(pDCE->hDC, DCHF_VALIDATEVISRGN);
}
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
}
HWND FASTCALL
IntWindowFromDC(HDC hDc)
{
DCE *Dce;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
HWND Ret = NULL;
- pLE = LEDce.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
+ Dce = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
if (Dce->hDC == hDc)
{
if (Dce->DCXFlags & DCX_INDESTROY)
Ret = Dce->hwndCurrent;
break;
}
- pLE = Dce->List.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
return Ret;
}
UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
{
PDCE dce;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
INT nRet = 0;
BOOL Hit = FALSE;
TRACE("%p %p\n", Window, hDc);
- pLE = LEDce.Flink;
- dce = CONTAINING_RECORD(pLE, DCE, List);
- do
+ ListEntry = LEDce.Flink;
+ while (ListEntry != &LEDce)
{
- if(!dce) break;
+ dce = CONTAINING_RECORD(ListEntry, DCE, List);
+ ListEntry = ListEntry->Flink;
if (dce->hDC == hDc)
{
Hit = TRUE;
break;
}
- pLE = dce->List.Flink;
- dce = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce );
if ( Hit && (dce->DCXFlags & DCX_DCEBUSY))
{
XCLIPOBJ* Clip;
PWND Wnd;
HWND hWnd;
- PPROPERTY pprop;
hWnd = IntWindowFromDC(hdc);
if (hWnd && (Wnd = UserGetWindowObject(hWnd)))
{
- pprop = IntGetProp(Wnd, AtomWndObj);
-
- Clip = (XCLIPOBJ*)pprop->Data;
+ Clip = (XCLIPOBJ*)UserGetProp(Wnd, AtomWndObj, TRUE);
if ( Clip && Clip->Hwnd == hWnd )
{
PWND Wnd=NULL;
DECLARE_RETURN(HDC);
- TRACE("Enter NtUserGetDCEx\n");
+ TRACE("Enter NtUserGetDCEx: hWnd %p, ClipRegion %p, Flags %x.\n",
+ hWnd, ClipRegion, Flags);
UserEnterExclusive();
if (hWnd && !(Wnd = UserGetWindowObject(hWnd)))