Partial clean-up of the painting functions:

- Get rid of the DCX_WINDOWPAINT flag (it wasn't used anyway).
- Remove the PaintPosted field from message queue, we don't need it.
- Use screen cooridnates for the WindowUpdate region instead of window relative ones.
- Fix the algorithm for retrieving paint messages to respect the painting order.
- Remove the NCUpdateRegion field from window object and calculate it on demand.
- Fix GetDCEx to take region in screen coordinates.

svn path=/trunk/; revision=17931
This commit is contained in:
Filip Navara 2005-09-19 10:39:26 +00:00
parent 0558c3abc5
commit 1d878e0ba5
9 changed files with 295 additions and 332 deletions

View file

@ -39,7 +39,7 @@ typedef struct tagDCE
#define DCX_DCEEMPTY 0x00000800 #define DCX_DCEEMPTY 0x00000800
#define DCX_DCEBUSY 0x00001000 #define DCX_DCEBUSY 0x00001000
#define DCX_DCEDIRTY 0x00002000 #define DCX_DCEDIRTY 0x00002000
#define DCX_WINDOWPAINT 0x00020000 #define DCX_USESTYLE 0x00010000
#define DCX_KEEPCLIPRGN 0x00040000 #define DCX_KEEPCLIPRGN 0x00040000
#define DCX_NOCLIPCHILDREN 0x00080000 #define DCX_NOCLIPCHILDREN 0x00080000

View file

@ -81,8 +81,6 @@ typedef struct _USER_MESSAGE_QUEUE
ULONG LastMsgRead; ULONG LastMsgRead;
/* Current window with focus (ie. receives keyboard input) for this queue. */ /* Current window with focus (ie. receives keyboard input) for this queue. */
HWND FocusWindow; HWND FocusWindow;
/* True if a window needs painting. */
BOOLEAN PaintPosted;
/* Count of paints pending. */ /* Count of paints pending. */
ULONG PaintCount; ULONG PaintCount;
/* Current active window for this queue. */ /* Current active window for this queue. */

View file

@ -60,7 +60,6 @@ typedef struct _WINDOW_OBJECT
UINT IDMenu; UINT IDMenu;
/* Handle of region of the window to be updated. */ /* Handle of region of the window to be updated. */
HANDLE UpdateRegion; HANDLE UpdateRegion;
HANDLE NCUpdateRegion;
/* Handle of the window region. */ /* Handle of the window region. */
HANDLE WindowRegion; HANDLE WindowRegion;
/* Pointer to the owning thread's message queue. */ /* Pointer to the owning thread's message queue. */

View file

@ -103,7 +103,6 @@ VOID FASTCALL
MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
{ {
Queue->PaintCount++; Queue->PaintCount++;
Queue->PaintPosted = TRUE;
Queue->QueueBits |= QS_PAINT; Queue->QueueBits |= QS_PAINT;
Queue->ChangedBits |= QS_PAINT; Queue->ChangedBits |= QS_PAINT;
if (Queue->WakeMask & QS_PAINT) if (Queue->WakeMask & QS_PAINT)
@ -114,10 +113,6 @@ VOID FASTCALL
MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
{ {
Queue->PaintCount--; Queue->PaintCount--;
if (Queue->PaintCount == 0)
{
Queue->PaintPosted = FALSE;
}
} }
@ -1341,7 +1336,6 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu
KeQueryTickCount(&LargeTickCount); KeQueryTickCount(&LargeTickCount);
MessageQueue->LastMsgRead = LargeTickCount.u.LowPart; MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
MessageQueue->FocusWindow = NULL; MessageQueue->FocusWindow = NULL;
MessageQueue->PaintPosted = FALSE;
MessageQueue->PaintCount = 0; MessageQueue->PaintCount = 0;
MessageQueue->WakeMask = ~0; MessageQueue->WakeMask = ~0;
MessageQueue->NewMessagesHandle = NULL; MessageQueue->NewMessagesHandle = NULL;

View file

@ -35,10 +35,52 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#define DCX_USESTYLE 0x10000
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
/**
* @name IntIntersectWithParents
*
* Intersect window rectangle with all parent client rectangles.
*
* @param Child
* Pointer to child window to start intersecting from.
* @param WindowRect
* Pointer to rectangle that we want to intersect in screen
* coordinates on input and intersected rectangle on output (if TRUE
* is returned).
*
* @return
* If any parent is minimized or invisible or the resulting rectangle
* is empty then FALSE is returned. Otherwise TRUE is returned.
*/
BOOL FASTCALL
IntIntersectWithParents(PWINDOW_OBJECT Child, PRECT WindowRect)
{
PWINDOW_OBJECT ParentWindow;
ParentWindow = Child->Parent;
while (ParentWindow != NULL)
{
if (!(ParentWindow->Style & WS_VISIBLE) ||
(ParentWindow->Style & WS_MINIMIZE))
{
return FALSE;
}
if (!IntGdiIntersectRect(WindowRect, WindowRect, &ParentWindow->ClientRect))
{
return FALSE;
}
/* FIXME: Layered windows. */
ParentWindow = ParentWindow->Parent;
}
return TRUE;
}
VOID FASTCALL VOID FASTCALL
IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion) IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
{ {
@ -46,30 +88,130 @@ IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
while (ParentWindow) while (ParentWindow)
{ {
if (!(ParentWindow->Style & WS_CLIPCHILDREN)) if (ParentWindow->Style & WS_CLIPCHILDREN)
{ break;
if (ParentWindow->UpdateRegion != 0)
{
INT OffsetX, OffsetY;
/* if (ParentWindow->UpdateRegion != 0)
* We must offset the child region by the offset of the {
* child rect in the parent. NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion,
*/ ValidRegion, RGN_DIFF);
OffsetX = Child->WindowRect.left - ParentWindow->WindowRect.left; /* FIXME: If the resulting region is empty, remove fake posted paint message */
OffsetY = Child->WindowRect.top - ParentWindow->WindowRect.top;
NtGdiOffsetRgn(ValidRegion, OffsetX, OffsetY);
NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion,
ValidRegion, RGN_DIFF);
/* FIXME: If the resulting region is empty, remove fake posted paint message */
NtGdiOffsetRgn(ValidRegion, -OffsetX, -OffsetY);
}
} }
ParentWindow = ParentWindow->Parent; ParentWindow = ParentWindow->Parent;
} }
} }
/**
* @name IntCalcWindowRgn
*
* Get a window or client region.
*/
HRGN FASTCALL
IntCalcWindowRgn(PWINDOW_OBJECT Window, BOOL Client)
{
HRGN hRgnWindow;
UINT RgnType;
if (Client)
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
else
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
if (Window->WindowRegion != NULL && !(Window->Style & WS_MINIMIZE))
{
NtGdiOffsetRgn(hRgnWindow,
-Window->WindowRect.left,
-Window->WindowRect.top);
RgnType = NtGdiCombineRgn(hRgnWindow, hRgnWindow, Window->WindowRegion, RGN_AND);
NtGdiOffsetRgn(hRgnWindow,
Window->WindowRect.left,
Window->WindowRect.top);
}
return hRgnWindow;
}
/**
* @name IntGetNCUpdateRgn
*
* Get non-client update region of a window and optionally validate it.
*
* @param Window
* Pointer to window to get the NC update region from.
* @param Validate
* Set to TRUE to force validating the NC update region.
*
* @return
* Handle to NC update region. The caller is responsible for deleting
* it.
*/
HRGN FASTCALL
IntGetNCUpdateRgn(PWINDOW_OBJECT Window, BOOL Validate)
{
HRGN hRgnNonClient;
HRGN hRgnWindow;
UINT RgnType;
if (Window->UpdateRegion != NULL &&
Window->UpdateRegion != (HRGN)1)
{
hRgnNonClient = NtGdiCreateRectRgn(0, 0, 0, 0);
hRgnWindow = IntCalcWindowRgn(Window, TRUE);
/*
* If region creation fails it's safe to fallback to whole
* window region.
*/
if (hRgnNonClient == NULL)
{
return (HRGN)1;
}
RgnType = NtGdiCombineRgn(hRgnNonClient, Window->UpdateRegion,
hRgnWindow, RGN_DIFF);
if (RgnType == ERROR)
{
NtGdiDeleteObject(hRgnNonClient);
return (HRGN)1;
}
else if (RgnType == NULLREGION)
{
NtGdiDeleteObject(hRgnNonClient);
return NULL;
}
/*
* Remove the nonclient region from the standard update region if
* we were asked for it.
*/
if (Validate)
{
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
hRgnWindow, RGN_AND) == NULLREGION)
{
GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
if (!(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT))
MsqDecPaintCountQueue(Window->MessageQueue);
}
}
NtGdiDeleteObject(hRgnWindow);
return hRgnNonClient;
}
else
{
return Window->UpdateRegion;
}
}
/* /*
* IntPaintWindows * IntPaintWindows
* *
@ -85,44 +227,37 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW)) if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{ {
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) if (Window->UpdateRegion)
{ {
if (Window->NCUpdateRegion) IntValidateParent(Window, Window->UpdateRegion);
{
IntValidateParent(Window, Window->NCUpdateRegion);
}
TempRegion = Window->NCUpdateRegion;
if ((HANDLE) 1 != TempRegion && NULL != TempRegion)
{
GDIOBJ_SetOwnership(TempRegion, PsGetCurrentProcess());
}
Window->NCUpdateRegion = NULL;
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue);
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
if ((HANDLE) 1 != TempRegion && NULL != TempRegion)
{
/* NOTE: The region can already be deleted! */
GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
}
} }
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) if (Flags & RDW_UPDATENOW)
{ {
if (Window->UpdateRegion) if (Window->UpdateRegion != NULL ||
Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{ {
/* co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
* This surely wrong! Why we would want to validate the parent? }
* It breaks quite a few things including dummy WM_ERASEBKGND }
* implementations that return only TRUE and have corresponding else
* WM_PAINT that doesn't paint the whole client area. {
* I left the code here so that no one will readd it again! if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
* - Filip {
*/ TempRegion = IntGetNCUpdateRgn(Window, TRUE);
/* IntValidateParent(Window, Window->UpdateRegion); */ Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE | MsqDecPaintCountQueue(Window->MessageQueue);
DCX_INTERSECTUPDATE); co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
if (hDC != NULL) if ((HANDLE) 1 != TempRegion && NULL != TempRegion)
{
/* NOTE: The region can already be deleted! */
GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
}
}
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
{
if (Window->UpdateRegion)
{ {
if (co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0)) if (co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0))
{ {
@ -132,22 +267,12 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
} }
} }
} }
if (Flags & RDW_UPDATENOW)
{
if (Window->UpdateRegion != NULL ||
Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
}
}
} }
/* /*
* Check that the window is still valid at this point * Check that the window is still valid at this point
*/ */
if (!IntIsWindow(hWnd))
if (! IntIsWindow(hWnd))
{ {
return; return;
} }
@ -156,7 +281,7 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
* Paint child windows. * Paint child windows.
*/ */
if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) && if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN))) ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)))
{ {
HWND *List, *phWnd; HWND *List, *phWnd;
@ -164,13 +289,11 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{ {
for (phWnd = List; *phWnd; ++phWnd) for (phWnd = List; *phWnd; ++phWnd)
{ {
Window = UserGetWindowObject(*phWnd); Window = IntGetWindowObject(*phWnd);
if (Window && (Window->Style & WS_VISIBLE)) if (Window && (Window->Style & WS_VISIBLE))
{ {
UserRefObjectCo(Window);
co_IntPaintWindows(Window, Flags); co_IntPaintWindows(Window, Flags);
UserDerefObjectCo(Window); ObmDereferenceObject(Window);
} }
} }
ExFreePool(List); ExFreePool(List);
@ -200,15 +323,18 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
HRGN hRgnWindow; HRGN hRgnWindow;
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
NtGdiOffsetRgn(hRgnWindow,
-Window->WindowRect.left,
-Window->WindowRect.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND); RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
NtGdiDeleteObject(hRgnWindow); NtGdiDeleteObject(hRgnWindow);
} }
else else
{ {
NtGdiOffsetRgn(hRgn,
-Window->WindowRect.left,
-Window->WindowRect.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND); RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND);
NtGdiOffsetRgn(hRgn,
Window->WindowRect.left,
Window->WindowRect.top);
} }
/* /*
@ -278,60 +404,6 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
} }
/*
* Split the nonclient update region.
*/
if (NULL != Window->UpdateRegion)
{
HRGN hRgnWindow, hRgnNonClient;
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
NtGdiOffsetRgn(hRgnWindow,
-Window->WindowRect.left,
-Window->WindowRect.top);
hRgnNonClient = NtGdiCreateRectRgn(0, 0, 0, 0);
if (NtGdiCombineRgn(hRgnNonClient, Window->UpdateRegion,
hRgnWindow, RGN_DIFF) == NULLREGION)
{
NtGdiDeleteObject(hRgnNonClient);
hRgnNonClient = NULL;
}
else
{
GDIOBJ_SetOwnership(hRgnNonClient, NULL);
}
/*
* Remove the nonclient region from the standard update region.
*/
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
hRgnWindow, RGN_AND) == NULLREGION)
{
GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
if (Window->NCUpdateRegion == NULL)
{
Window->NCUpdateRegion = hRgnNonClient;
}
else
{
if(NULL != hRgnNonClient)
{
NtGdiCombineRgn(Window->NCUpdateRegion, Window->NCUpdateRegion,
hRgnNonClient, RGN_OR);
GDIOBJ_SetOwnership(hRgnNonClient, PsGetCurrentProcess());
NtGdiDeleteObject(hRgnNonClient);
}
}
NtGdiDeleteObject(hRgnWindow);
}
/* /*
* Process children if needed * Process children if needed
*/ */
@ -358,9 +430,6 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
*/ */
HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0); HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY); NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
NtGdiOffsetRgn(hRgnTemp,
Window->WindowRect.left - Child->WindowRect.left,
Window->WindowRect.top - Child->WindowRect.top);
IntInvalidateWindows(Child, hRgnTemp, Flags); IntInvalidateWindows(Child, hRgnTemp, Flags);
NtGdiDeleteObject(hRgnTemp); NtGdiDeleteObject(hRgnTemp);
} }
@ -407,20 +476,16 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
BOOL FASTCALL BOOL FASTCALL
IntIsWindowDrawable(PWINDOW_OBJECT Window) IntIsWindowDrawable(PWINDOW_OBJECT Window)
{ {
PWINDOW_OBJECT Wnd = Window; PWINDOW_OBJECT Wnd;
do for (Wnd = Window; Wnd != NULL; Wnd = Wnd->Parent)
{ {
if (!(Wnd->Style & WS_VISIBLE) || if (!(Wnd->Style & WS_VISIBLE) ||
((Wnd->Style & WS_MINIMIZE) && (Wnd != Window))) ((Wnd->Style & WS_MINIMIZE) && (Wnd != Window)))
{ {
return FALSE; return FALSE;
} }
Wnd = Wnd->Parent;
} }
while(Wnd);
return TRUE; return TRUE;
} }
@ -453,7 +518,7 @@ co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRg
/* /*
* Step 2. * Step 2.
* Transform the parameters UpdateRgn and UpdateRect into * Transform the parameters UpdateRgn and UpdateRect into
* a region hRgn specified in window coordinates. * a region hRgn specified in screen coordinates.
*/ */
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) if (Flags & (RDW_INVALIDATE | RDW_VALIDATE))
@ -461,35 +526,30 @@ co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRg
if (UpdateRgn != NULL) if (UpdateRgn != NULL)
{ {
hRgn = NtGdiCreateRectRgn(0, 0, 0, 0); hRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY); if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
NtGdiOffsetRgn(hRgn, NtGdiDeleteObject(hRgn);
Window->ClientRect.left - Window->WindowRect.left, else
Window->ClientRect.top - Window->WindowRect.top); NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top);
} }
else else if (UpdateRect != NULL)
if (UpdateRect != NULL) {
if (!IntGdiIsEmptyRect(UpdateRect))
{ {
hRgn = UnsafeIntCreateRectRgnIndirect((RECT *)UpdateRect); hRgn = UnsafeIntCreateRectRgnIndirect((RECT *)UpdateRect);
NtGdiOffsetRgn(hRgn, NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top);
Window->ClientRect.left - Window->WindowRect.left,
Window->ClientRect.top - Window->WindowRect.top);
} }
else }
if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) || else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
(Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME)) (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
{ {
hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); if (!IntGdiIsEmptyRect(&Window->WindowRect))
NtGdiOffsetRgn(hRgn, hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
-Window->WindowRect.left, }
-Window->WindowRect.top); else
} {
else if (!IntGdiIsEmptyRect(&Window->ClientRect))
{ hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); }
NtGdiOffsetRgn(hRgn,
-Window->WindowRect.left,
-Window->WindowRect.top);
}
} }
/* /*
@ -497,7 +557,8 @@ co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRg
* Adjust the window update region depending on hRgn and flags. * Adjust the window update region depending on hRgn and flags.
*/ */
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT)) if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) &&
hRgn != NULL)
{ {
IntInvalidateWindows(Window, hRgn, Flags); IntInvalidateWindows(Window, hRgn, Flags);
} }
@ -534,84 +595,55 @@ IntIsWindowDirty(PWINDOW_OBJECT Window)
(Window->Flags & WINDOWOBJECT_NEED_NCPAINT)); (Window->Flags & WINDOWOBJECT_NEED_NCPAINT));
} }
HWND STDCALL HWND FASTCALL
IntFindWindowToRepaint(HWND hWnd, PW32THREAD Thread) IntFindWindowToRepaint(PWINDOW_OBJECT Window, PW32THREAD Thread)
{ {
PWINDOW_OBJECT Window; HWND hChild;
PWINDOW_OBJECT Child;
HWND hFoundWnd = NULL;
if (!(Window = UserGetWindowObject(hWnd))) while (Window != NULL)
return NULL;
if (IntIsWindowDirty(Window) &&
IntWndBelongsToThread(Window, Thread))
{ {
return hWnd; /* FIXME: Transparent windows. */
} if (IntIsWindowDirty(Window) &&
IntWndBelongsToThread(Window, Thread))
for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
if (IntIsWindowDirty(Child) &&
IntWndBelongsToThread(Child, Thread))
{ {
hFoundWnd = Child->hSelf; return Window->hSelf;
break;
} }
}
if (hFoundWnd == NULL) if (Window->FirstChild)
{
HWND *List;
INT i;
List = IntWinListChildren(Window);
if (List != NULL)
{ {
for (i = 0; List[i]; i++) hChild = IntFindWindowToRepaint(Window->FirstChild, Thread);
{ if (hChild != NULL)
hFoundWnd = IntFindWindowToRepaint(List[i], Thread); return hChild;
if (hFoundWnd != NULL)
break;
}
ExFreePool(List);
} }
Window = Window->NextSibling;
} }
return hFoundWnd; return NULL;
} }
BOOL FASTCALL BOOL FASTCALL
IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax,
PW32THREAD Thread, MSG *Message, BOOL Remove) PW32THREAD Thread, MSG *Message, BOOL Remove)
{ {
PWINDOW_OBJECT Window;
PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue; PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
if (!MessageQueue->PaintPosted) if (!MessageQueue->PaintCount)
return FALSE; return FALSE;
if ((MsgFilterMin != 0 || MsgFilterMax != 0) && if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
(MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT)) (MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
return FALSE; return FALSE;
if (hWnd) Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetWin32Thread());
Message->hwnd = IntFindWindowToRepaint(hWnd, PsGetWin32Thread());
else
Message->hwnd = IntFindWindowToRepaint(IntGetDesktopWindow(), PsGetWin32Thread());
if (Message->hwnd == NULL) if (Message->hwnd == NULL)
{ {
if (NULL == hWnd) DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
{
DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
MessageQueue->PaintPosted = 0;
MessageQueue->PaintCount = 0;
}
return FALSE; return FALSE;
} }
if (!(Window = UserGetWindowObject(Message->hwnd))) if (hWnd != NULL && Message->hwnd != hWnd)
return FALSE; return FALSE;
Message->message = WM_PAINT; Message->message = WM_PAINT;
@ -700,14 +732,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
{ {
HRGN hRgn; HRGN hRgn;
if (Window->NCUpdateRegion != (HANDLE)1 && hRgn = IntGetNCUpdateRgn(Window, FALSE);
Window->NCUpdateRegion != NULL)
{
GDIOBJ_SetOwnership(Window->NCUpdateRegion, PsGetCurrentProcess());
}
hRgn = Window->NCUpdateRegion;
IntValidateParent(Window, Window->NCUpdateRegion);
Window->NCUpdateRegion = NULL;
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue); MsqDecPaintCountQueue(Window->MessageQueue);
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0); co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
@ -720,8 +745,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT)); RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT));
Ps.hdc = UserGetDCEx(Window, 0, DCX_INTERSECTUPDATE | DCX_WINDOWPAINT | DCX_USESTYLE); Ps.hdc = UserGetDCEx(Window, Window->UpdateRegion, DCX_INTERSECTRGN | DCX_USESTYLE);
if (!Ps.hdc) if (!Ps.hdc)
{ {
RETURN( NULL); RETURN( NULL);
@ -730,22 +754,20 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
if (Window->UpdateRegion != NULL) if (Window->UpdateRegion != NULL)
{ {
MsqDecPaintCountQueue(Window->MessageQueue); MsqDecPaintCountQueue(Window->MessageQueue);
IntValidateParent(Window, Window->UpdateRegion);
Rgn = RGNDATA_LockRgn(Window->UpdateRegion); Rgn = RGNDATA_LockRgn(Window->UpdateRegion);
if (NULL != Rgn) if (NULL != Rgn)
{ {
UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint); UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint);
RGNDATA_UnlockRgn(Rgn); RGNDATA_UnlockRgn(Rgn);
IntGdiOffsetRect(&Ps.rcPaint, IntGdiOffsetRect(&Ps.rcPaint,
Window->WindowRect.left - Window->ClientRect.left, -Window->ClientRect.left,
Window->WindowRect.top - Window->ClientRect.top); -Window->ClientRect.top);
} }
else else
{ {
IntGetClientRect(Window, &Ps.rcPaint); IntGetClientRect(Window, &Ps.rcPaint);
} }
GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess()); GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL; Window->UpdateRegion = NULL;
} }
else else
@ -755,6 +777,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
IntGetClientRect(Window, &Ps.rcPaint); IntGetClientRect(Window, &Ps.rcPaint);
} }
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
@ -898,10 +921,7 @@ co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase)
else else
{ {
RegionType = NtGdiCombineRgn(hRgn, Window->UpdateRegion, hRgn, RGN_COPY); RegionType = NtGdiCombineRgn(hRgn, Window->UpdateRegion, hRgn, RGN_COPY);
NtGdiOffsetRgn( NtGdiOffsetRgn(hRgn, -Window->ClientRect.left, -Window->ClientRect.top);
hRgn,
Window->WindowRect.left - Window->ClientRect.left,
Window->WindowRect.top - Window->ClientRect.top);
} }
if (bErase && RegionType != NULLREGION && RegionType != ERROR) if (bErase && RegionType != NULLREGION && RegionType != ERROR)

View file

@ -38,37 +38,30 @@ VIS_ComputeVisibleRegion(
BOOLEAN ClipSiblings) BOOLEAN ClipSiblings)
{ {
HRGN VisRgn, ClipRgn; HRGN VisRgn, ClipRgn;
INT LeftOffset, TopOffset;
PWINDOW_OBJECT PreviousWindow, CurrentWindow, CurrentSibling; PWINDOW_OBJECT PreviousWindow, CurrentWindow, CurrentSibling;
if (!(Window->Style & WS_VISIBLE)) if (!(Window->Style & WS_VISIBLE))
{ {
return NtGdiCreateRectRgn(0, 0, 0, 0); return NULL;
} }
if (ClientArea) if (ClientArea)
{ {
if(!(ClipRgn = VIS_ComputeVisibleRegion(Window, FALSE, ClipChildren, ClipSiblings))) if (!(ClipRgn = VIS_ComputeVisibleRegion(Window, FALSE, ClipChildren, ClipSiblings)))
{ {
return NtGdiCreateRectRgn(0, 0, 0, 0); return NULL;
} }
if(!(VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect))) if (!(VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect)))
{ {
NtGdiDeleteObject(VisRgn); NtGdiDeleteObject(VisRgn);
return NtGdiCreateRectRgn(0, 0, 0, 0); return NULL;
} }
LeftOffset = Window->ClientRect.left - Window->WindowRect.left;
TopOffset = Window->ClientRect.top - Window->WindowRect.top;
NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
NtGdiDeleteObject(ClipRgn); NtGdiDeleteObject(ClipRgn);
NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset);
return VisRgn; return VisRgn;
} }
VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
LeftOffset = Window->WindowRect.left;
TopOffset = Window->WindowRect.top;
/* /*
* Walk through all parent windows and for each clip the visble region * Walk through all parent windows and for each clip the visble region
@ -83,14 +76,15 @@ VIS_ComputeVisibleRegion(
if (!(CurrentWindow->Style & WS_VISIBLE)) if (!(CurrentWindow->Style & WS_VISIBLE))
{ {
NtGdiDeleteObject(VisRgn); NtGdiDeleteObject(VisRgn);
return NtGdiCreateRectRgn(0, 0, 0, 0); return NULL;
} }
ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->ClientRect); ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->ClientRect);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
NtGdiDeleteObject(ClipRgn); NtGdiDeleteObject(ClipRgn);
if ((PreviousWindow->Style & WS_CLIPSIBLINGS) || if ((PreviousWindow->Style & WS_CLIPSIBLINGS) ||
(PreviousWindow == Window && ClipSiblings)) (PreviousWindow == Window && ClipSiblings))
{ {
CurrentSibling = CurrentWindow->FirstChild; CurrentSibling = CurrentWindow->FirstChild;
while (CurrentSibling != NULL && CurrentSibling != PreviousWindow) while (CurrentSibling != NULL && CurrentSibling != PreviousWindow)
@ -99,7 +93,7 @@ VIS_ComputeVisibleRegion(
{ {
ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentSibling->WindowRect); ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentSibling->WindowRect);
/* Combine it with the window region if available */ /* Combine it with the window region if available */
if(CurrentSibling->WindowRegion && !(CurrentSibling->Style & WS_MINIMIZE)) if (CurrentSibling->WindowRegion && !(CurrentSibling->Style & WS_MINIMIZE))
{ {
NtGdiOffsetRgn(ClipRgn, -CurrentSibling->WindowRect.left, -CurrentSibling->WindowRect.top); NtGdiOffsetRgn(ClipRgn, -CurrentSibling->WindowRect.left, -CurrentSibling->WindowRect.top);
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->WindowRegion, RGN_AND); NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->WindowRegion, RGN_AND);
@ -125,7 +119,7 @@ VIS_ComputeVisibleRegion(
{ {
ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->WindowRect); ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->WindowRect);
/* Combine it with the window region if available */ /* Combine it with the window region if available */
if(CurrentWindow->WindowRegion && !(CurrentWindow->Style & WS_MINIMIZE)) if (CurrentWindow->WindowRegion && !(CurrentWindow->Style & WS_MINIMIZE))
{ {
NtGdiOffsetRgn(ClipRgn, -CurrentWindow->WindowRect.left, -CurrentWindow->WindowRect.top); NtGdiOffsetRgn(ClipRgn, -CurrentWindow->WindowRect.left, -CurrentWindow->WindowRect.top);
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->WindowRegion, RGN_AND); NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->WindowRegion, RGN_AND);
@ -138,15 +132,13 @@ VIS_ComputeVisibleRegion(
} }
} }
if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE)) if (Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
{ {
NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset); NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND); NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND);
return VisRgn; NtGdiOffsetRgn(VisRgn, Window->WindowRect.left, Window->WindowRect.top);
} }
NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset);
return VisRgn; return VisRgn;
} }

View file

@ -34,8 +34,6 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#define DCX_USESTYLE 0x10000
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
/* NOTE - I think we should store this per window station (including gdi objects) */ /* NOTE - I think we should store this per window station (including gdi objects) */
@ -187,7 +185,7 @@ DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL, HDC hDC, ULONG Flags,
STATIC VOID FASTCALL STATIC VOID FASTCALL
DceDeleteClipRgn(DCE* Dce) DceDeleteClipRgn(DCE* Dce)
{ {
Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT); Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN);
if (Dce->DCXFlags & DCX_KEEPCLIPRGN ) if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
{ {
@ -216,7 +214,7 @@ DceReleaseDC(DCE* dce)
/* restore previous visible region */ /* restore previous visible region */
if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) && if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
(dce->DCXFlags & (DCX_CACHE | DCX_WINDOWPAINT)) ) (dce->DCXFlags & DCX_CACHE) )
{ {
DceDeleteClipRgn(dce); DceDeleteClipRgn(dce);
} }
@ -273,23 +271,6 @@ DceUpdateVisRgn(DCE *Dce, PWINDOW_OBJECT Window, ULONG Flags)
{ {
hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0); hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
} }
else
{
if (0 == (Flags & DCX_WINDOW))
{
NtGdiOffsetRgn(
hRgnVisible,
Parent->ClientRect.left - Window->ClientRect.left,
Parent->ClientRect.top - Window->ClientRect.top);
}
else
{
NtGdiOffsetRgn(
hRgnVisible,
Parent->WindowRect.left - Window->WindowRect.left,
Parent->WindowRect.top - Window->WindowRect.top);
}
}
} }
else if (Window == NULL) else if (Window == NULL)
{ {
@ -482,7 +463,7 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
} }
Dce->hwndCurrent = (Window ? Window->hSelf : NULL); Dce->hwndCurrent = (Window ? Window->hSelf : NULL);
Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY; Dce->DCXFlags = DcxFlags | DCX_DCEBUSY;
if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion) if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)
{ {
@ -498,21 +479,8 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
if (0 != (Flags & DCX_INTERSECTUPDATE) && NULL == ClipRegion) if (0 != (Flags & DCX_INTERSECTUPDATE) && NULL == ClipRegion)
{ {
Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); Flags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN;
if (Dce->hClipRgn && Window->UpdateRegion) ClipRegion = Window->UpdateRegion;
{
GDIOBJ_SetOwnership(Dce->hClipRgn, NULL);
NtGdiCombineRgn(Dce->hClipRgn, Window->UpdateRegion, NULL, RGN_COPY);
if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND);
if (!(Flags & DCX_WINDOW))
{
NtGdiOffsetRgn(Dce->hClipRgn,
Window->WindowRect.left - Window->ClientRect.left,
Window->WindowRect.top - Window->ClientRect.top);
}
}
Flags |= DCX_INTERSECTRGN;
} }
if (ClipRegion == (HRGN) 1) if (ClipRegion == (HRGN) 1)
@ -521,40 +489,17 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
{ {
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); GDIOBJ_SetOwnership(Dce->hClipRgn, NULL);
if(!Window->WindowRegion || (Window->Style & WS_MINIMIZE))
{
NtGdiOffsetRgn(Dce->hClipRgn, -Window->ClientRect.left, -Window->ClientRect.top);
}
else
{
NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left, -Window->WindowRect.top);
NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND);
NtGdiOffsetRgn(Dce->hClipRgn, -(Window->ClientRect.left - Window->WindowRect.left),
-(Window->ClientRect.top - Window->WindowRect.top));
}
} }
else else
{ {
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); GDIOBJ_SetOwnership(Dce->hClipRgn, NULL);
NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left,
-Window->WindowRect.top);
if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND);
} }
} }
else if (NULL != ClipRegion) else if (ClipRegion != NULL)
{ {
Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); Dce->hClipRgn = ClipRegion;
if (Dce->hClipRgn) GDIOBJ_SetOwnership(Dce->hClipRgn, NULL);
{
GDIOBJ_SetOwnership(Dce->hClipRgn, NULL);
if(!Window->WindowRegion || (Window->Style & WS_MINIMIZE))
NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY);
else
NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, Window->WindowRegion, RGN_AND);
}
NtGdiDeleteObject(ClipRegion);
} }
DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin); DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);
@ -705,9 +650,9 @@ DceFreeDCE(PDCE dce, BOOLEAN Force)
} }
NtGdiDeleteDC(dce->hDC); NtGdiDeleteDC(dce->hDC);
GDIOBJ_SetOwnership(dce->hClipRgn, PsGetCurrentProcess());
if (dce->hClipRgn && ! (dce->DCXFlags & DCX_KEEPCLIPRGN)) if (dce->hClipRgn && ! (dce->DCXFlags & DCX_KEEPCLIPRGN))
{ {
GDIOBJ_SetOwnership(dce->hClipRgn, PsGetCurrentProcess());
NtGdiDeleteObject(dce->hClipRgn); NtGdiDeleteObject(dce->hClipRgn);
} }

View file

@ -959,6 +959,7 @@ co_WinPosSetWindowPos(
else if(VisRgn) else if(VisRgn)
{ {
RGNDATA_UnlockRgn(VisRgn); RGNDATA_UnlockRgn(VisRgn);
NtGdiOffsetRgn(VisBefore, -Window->WindowRect.left, -Window->WindowRect.top);
} }
} }
} }
@ -1081,6 +1082,13 @@ co_WinPosSetWindowPos(
Window->Style |= WS_VISIBLE; Window->Style |= WS_VISIBLE;
} }
if (Window->UpdateRegion != NULL && Window->UpdateRegion != (HRGN)1)
{
NtGdiOffsetRgn(Window->UpdateRegion,
NewWindowRect.left - OldWindowRect.left,
NewWindowRect.top - OldWindowRect.top);
}
DceResetActiveDCEs(Window); DceResetActiveDCEs(Window);
if (!(WinPos.flags & SWP_NOREDRAW)) if (!(WinPos.flags & SWP_NOREDRAW))
@ -1099,6 +1107,7 @@ co_WinPosSetWindowPos(
else if(VisRgn) else if(VisRgn)
{ {
RGNDATA_UnlockRgn(VisRgn); RGNDATA_UnlockRgn(VisRgn);
NtGdiOffsetRgn(VisAfter, -Window->WindowRect.left, -Window->WindowRect.top);
} }
/* /*
@ -1136,11 +1145,9 @@ co_WinPosSetWindowPos(
/* No use in copying bits which are in the update region. */ /* No use in copying bits which are in the update region. */
if (Window->UpdateRegion != NULL) if (Window->UpdateRegion != NULL)
{ {
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF); NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
} NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
if (Window->NCUpdateRegion != NULL)
{
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->NCUpdateRegion, RGN_DIFF);
} }
/* /*
@ -1163,6 +1170,7 @@ co_WinPosSetWindowPos(
{ {
RGNDATA_UnlockRgn(VisRgn); RGNDATA_UnlockRgn(VisRgn);
} }
/* /*
* Small trick here: there is no function to bitblt a region. So * Small trick here: there is no function to bitblt a region. So
* we set the region as the clipping region, take the bounding box * we set the region as the clipping region, take the bounding box
@ -1172,11 +1180,10 @@ co_WinPosSetWindowPos(
* Since NtUserGetDCEx takes ownership of the clip region, we need * Since NtUserGetDCEx takes ownership of the clip region, we need
* to create a copy of CopyRgn and pass that. We need CopyRgn later * to create a copy of CopyRgn and pass that. We need CopyRgn later
*/ */
HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
Dc = UserGetDCEx(Window, CopyRgn, DCX_WINDOW | DCX_CACHE |
NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY); DCX_INTERSECTRGN | DCX_CLIPSIBLINGS |
Dc = UserGetDCEx(Window, ClipRgn, DCX_WINDOW | DCX_CACHE | DCX_KEEPCLIPRGN);
DCX_INTERSECTRGN | DCX_CLIPSIBLINGS);
NtGdiBitBlt(Dc, NtGdiBitBlt(Dc,
CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
CopyRect.bottom - CopyRect.top, Dc, CopyRect.bottom - CopyRect.top, Dc,
@ -1184,6 +1191,7 @@ co_WinPosSetWindowPos(
CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY); CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
UserReleaseDC(Window, Dc); UserReleaseDC(Window, Dc);
IntValidateParent(Window, CopyRgn); IntValidateParent(Window, CopyRgn);
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
} }
else if(VisRgn) else if(VisRgn)
{ {

View file

@ -83,10 +83,17 @@ NtGdiSelectVisRgn(HDC hdc, HRGN hrgn)
dc->w.hVisRgn = NtGdiCreateRectRgn(0, 0, 0, 0); dc->w.hVisRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
GDIOBJ_CopyOwnership(hdc, dc->w.hVisRgn); GDIOBJ_CopyOwnership(hdc, dc->w.hVisRgn);
} }
else
{
NtGdiOffsetRgn(dc->w.hVisRgn, dc->w.DCOrgX, dc->w.DCOrgY);
}
retval = NtGdiCombineRgn(dc->w.hVisRgn, hrgn, 0, RGN_COPY); retval = NtGdiCombineRgn(dc->w.hVisRgn, hrgn, 0, RGN_COPY);
if ( retval != ERROR ) if ( retval != ERROR )
CLIPPING_UpdateGCRegion(dc); {
NtGdiOffsetRgn(dc->w.hVisRgn, -dc->w.DCOrgX, -dc->w.DCOrgY);
CLIPPING_UpdateGCRegion(dc);
}
DC_UnlockDc(dc); DC_UnlockDc(dc);
return retval; return retval;