mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
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:
parent
0558c3abc5
commit
1d878e0ba5
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue