#define NDEBUG
#include <debug.h>
-#define DCX_USESTYLE 0x10000
-
/* 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
IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
{
while (ParentWindow)
{
- if (!(ParentWindow->Style & WS_CLIPCHILDREN))
+ if (ParentWindow->Style & WS_CLIPCHILDREN)
+ break;
+
+ if (ParentWindow->UpdateRegion != 0)
{
- if (ParentWindow->UpdateRegion != 0)
- {
- INT OffsetX, OffsetY;
+ NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion,
+ ValidRegion, RGN_DIFF);
+ /* FIXME: If the resulting region is empty, remove fake posted paint message */
+ }
- /*
- * We must offset the child region by the offset of the
- * child rect in the parent.
- */
- OffsetX = Child->WindowRect.left - ParentWindow->WindowRect.left;
- 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;
+ }
+}
+
+/**
+ * @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);
}
}
- ParentWindow = ParentWindow->Parent;
+ NtGdiDeleteObject(hRgnWindow);
+
+ return hRgnNonClient;
+ }
+ else
+ {
+ return Window->UpdateRegion;
}
}
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{
- if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
+ if (Window->UpdateRegion)
{
- if (Window->NCUpdateRegion)
- {
- IntValidateParent(Window, Window->NCUpdateRegion);
- }
- TempRegion = Window->NCUpdateRegion;
- if ((HANDLE) 1 != TempRegion && NULL != TempRegion)
+ IntValidateParent(Window, Window->UpdateRegion);
+ }
+
+ if (Flags & RDW_UPDATENOW)
+ {
+ if (Window->UpdateRegion != NULL ||
+ Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
- GDIOBJ_SetOwnership(TempRegion, PsGetCurrentProcess());
+ co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
}
- 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)
+ }
+ else
+ {
+ if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
- /* NOTE: The region can already be deleted! */
- GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
+ TempRegion = IntGetNCUpdateRgn(Window, TRUE);
+ 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 (Window->UpdateRegion)
+ if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
{
- /*
- * 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
- * WM_PAINT that doesn't paint the whole client area.
- * I left the code here so that no one will readd it again!
- * - Filip
- */
- /* IntValidateParent(Window, Window->UpdateRegion); */
- hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE |
- DCX_INTERSECTUPDATE);
- if (hDC != NULL)
+ if (Window->UpdateRegion)
{
+ hDC = UserGetDCEx(Window, Window->UpdateRegion,
+ DCX_CACHE | DCX_USESTYLE |
+ DCX_INTERSECTRGN | DCX_KEEPCLIPRGN);
if (co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0))
{
Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBKGND;
}
- UserReleaseDC(Window, hDC);
+ UserReleaseDC(Window, hDC, FALSE);
}
}
}
-
- 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
*/
-
- if (! IntIsWindow(hWnd))
+ if (!IntIsWindow(hWnd))
{
return;
}
* Paint child windows.
*/
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;
{
for (phWnd = List; *phWnd; ++phWnd)
{
- Window = IntGetWindowObject(*phWnd);
+ Window = UserGetWindowObject(*phWnd);
if (Window && (Window->Style & WS_VISIBLE))
{
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(Window, &Ref);
co_IntPaintWindows(Window, Flags);
- IntReleaseWindowObject(Window);
+ UserDerefObjectCo(Window);
}
}
ExFreePool(List);
HRGN hRgnWindow;
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
- NtGdiOffsetRgn(hRgnWindow,
- -Window->WindowRect.left,
- -Window->WindowRect.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
NtGdiDeleteObject(hRgnWindow);
}
else
{
+ NtGdiOffsetRgn(hRgn,
+ -Window->WindowRect.left,
+ -Window->WindowRect.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND);
+ NtGdiOffsetRgn(hRgn,
+ Window->WindowRect.left,
+ Window->WindowRect.top);
}
/*
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
*/
if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)))
{
- HWND *List, *phWnd;
PWINDOW_OBJECT Child;
- if ((List = IntWinListChildren(Window)))
+ for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
- for (phWnd = List; *phWnd; ++phWnd)
+ if (Child->Style & WS_VISIBLE)
{
- Child = IntGetWindowObject(*phWnd);
- if(!Child)
- {
- continue;
- }
- if (Child->Style & WS_VISIBLE)
- {
- /*
- * Recursive call to update children UpdateRegion
- */
- HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
- NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
- NtGdiOffsetRgn(hRgnTemp,
- Window->WindowRect.left - Child->WindowRect.left,
- Window->WindowRect.top - Child->WindowRect.top);
- IntInvalidateWindows(Child, hRgnTemp, Flags);
- NtGdiDeleteObject(hRgnTemp);
- }
- IntReleaseWindowObject(Child);
+ /*
+ * Recursive call to update children UpdateRegion
+ */
+ HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
+ NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
+ IntInvalidateWindows(Child, hRgnTemp, Flags);
+ NtGdiDeleteObject(hRgnTemp);
}
- ExFreePool(List);
+
}
}
BOOL FASTCALL
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) ||
((Wnd->Style & WS_MINIMIZE) && (Wnd != Window)))
{
return FALSE;
}
-
- Wnd = Wnd->Parent;
-
}
- while(Wnd);
return TRUE;
}
/*
* Step 2.
* 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 (UpdateRgn != NULL)
{
hRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
- NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY);
- NtGdiOffsetRgn(hRgn,
- Window->ClientRect.left - Window->WindowRect.left,
- Window->ClientRect.top - Window->WindowRect.top);
+ if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
+ NtGdiDeleteObject(hRgn);
+ else
+ NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top);
}
- else
- if (UpdateRect != NULL)
+ else if (UpdateRect != NULL)
+ {
+ if (!IntGdiIsEmptyRect(UpdateRect))
{
hRgn = UnsafeIntCreateRectRgnIndirect((RECT *)UpdateRect);
- NtGdiOffsetRgn(hRgn,
- Window->ClientRect.left - Window->WindowRect.left,
- Window->ClientRect.top - Window->WindowRect.top);
+ NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top);
}
- else
- if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
- (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
- {
- hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
- NtGdiOffsetRgn(hRgn,
- -Window->WindowRect.left,
- -Window->WindowRect.top);
- }
- else
- {
- hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
- NtGdiOffsetRgn(hRgn,
- -Window->WindowRect.left,
- -Window->WindowRect.top);
- }
+ }
+ else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
+ (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
+ {
+ if (!IntGdiIsEmptyRect(&Window->WindowRect))
+ hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
+ }
+ else
+ {
+ if (!IntGdiIsEmptyRect(&Window->ClientRect))
+ hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
+ }
}
/*
* 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);
}
(Window->Flags & WINDOWOBJECT_NEED_NCPAINT));
}
-HWND STDCALL
-IntFindWindowToRepaint(HWND hWnd, PW32THREAD Thread)
+HWND FASTCALL
+IntFindWindowToRepaint(PWINDOW_OBJECT Window, PW32THREAD Thread)
{
- PWINDOW_OBJECT Window;
- PWINDOW_OBJECT Child;
- HWND hFoundWnd = NULL;
-
- Window = IntGetWindowObject(hWnd);
- if (Window == NULL)
- return NULL;
+ HWND hChild;
+ PWINDOW_OBJECT TempWindow;
- if (IntIsWindowDirty(Window) &&
- IntWndBelongsToThread(Window, Thread))
+ for (; Window != NULL; Window = Window->NextSibling)
{
- IntReleaseWindowObject(Window);
- return hWnd;
- }
-
- for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
- {
- if (IntIsWindowDirty(Child) &&
- IntWndBelongsToThread(Child, Thread))
+ if (IntWndBelongsToThread(Window, Thread) &&
+ IntIsWindowDirty(Window))
{
- hFoundWnd = Child->hSelf;
- break;
- }
- }
+ /* Make sure all non-transparent siblings are already drawn. */
+ if (Window->ExStyle & WS_EX_TRANSPARENT)
+ {
+ for (TempWindow = Window->NextSibling; TempWindow != NULL;
+ TempWindow = TempWindow->NextSibling)
+ {
+ if (!(TempWindow->ExStyle & WS_EX_TRANSPARENT) &&
+ IntWndBelongsToThread(TempWindow, Thread) &&
+ IntIsWindowDirty(TempWindow))
+ {
+ return TempWindow->hSelf;
+ }
+ }
+ }
- if (hFoundWnd == NULL)
- {
- HWND *List;
- INT i;
+ return Window->hSelf;
+ }
- List = IntWinListChildren(Window);
- if (List != NULL)
+ if (Window->FirstChild)
{
- for (i = 0; List[i]; i++)
- {
- hFoundWnd = IntFindWindowToRepaint(List[i], Thread);
- if (hFoundWnd != NULL)
- break;
- }
- ExFreePool(List);
+ hChild = IntFindWindowToRepaint(Window->FirstChild, Thread);
+ if (hChild != NULL)
+ return hChild;
}
}
- IntReleaseWindowObject(Window);
-
- return hFoundWnd;
+ return NULL;
}
BOOL FASTCALL
IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax,
PW32THREAD Thread, MSG *Message, BOOL Remove)
{
- PWINDOW_OBJECT Window;
PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
- if (!MessageQueue->PaintPosted)
+ if (!MessageQueue->PaintCount)
return FALSE;
if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
(MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
return FALSE;
- if (hWnd)
- Message->hwnd = IntFindWindowToRepaint(hWnd, PsGetWin32Thread());
- else
- Message->hwnd = IntFindWindowToRepaint(IntGetDesktopWindow(), PsGetWin32Thread());
+ Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetWin32Thread());
if (Message->hwnd == NULL)
{
- if (NULL == hWnd)
- {
- DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
- MessageQueue->PaintPosted = 0;
- MessageQueue->PaintCount = 0;
- }
+ DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
return FALSE;
}
- Window = IntGetWindowObject(Message->hwnd);
- if (Window != NULL)
- {
- Message->message = WM_PAINT;
- Message->wParam = Message->lParam = 0;
- IntReleaseWindowObject(Window);
+ if (hWnd != NULL && Message->hwnd != hWnd)
+ return FALSE;
- return TRUE;
- }
+ Message->message = WM_PAINT;
+ Message->wParam = Message->lParam = 0;
- return FALSE;
+ return TRUE;
}
static
ASSERT_REFS_CO(Window);
- Desktop = PsGetCurrentThread()->Tcb.Win32Thread->Desktop;
+ Desktop = ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->Desktop;
CaretInfo = ((PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue)->CaretInfo;
hWndCaret = CaretInfo->hWnd;
WndCaret = UserGetWindowObject(hWndCaret);
+ //fix: check for WndCaret can be null
if (WndCaret == Window ||
- ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window->hSelf, hWndCaret)))
+ ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
{
POINT pt, FromOffset, ToOffset, Offset;
RECT rcCaret;
HDC STDCALL
NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
{
- PWINDOW_OBJECT Window;
+ PWINDOW_OBJECT Window = NULL;
PAINTSTRUCT Ps;
PROSRGNDATA Rgn;
NTSTATUS Status;
DECLARE_RETURN(HDC);
+ USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserBeginPaint\n");
UserEnterExclusive();
- if (!(Window = IntGetWindowObject(hWnd)))
+ if (!(Window = UserGetWindowObject(hWnd)))
{
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
RETURN( NULL);
}
+ UserRefObjectCo(Window, &Ref);
+
co_UserHideCaret(Window);
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
HRGN hRgn;
- if (Window->NCUpdateRegion != (HANDLE)1 &&
- Window->NCUpdateRegion != NULL)
- {
- GDIOBJ_SetOwnership(Window->NCUpdateRegion, PsGetCurrentProcess());
- }
- hRgn = Window->NCUpdateRegion;
- IntValidateParent(Window, Window->NCUpdateRegion);
- Window->NCUpdateRegion = NULL;
+ hRgn = IntGetNCUpdateRgn(Window, FALSE);
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue);
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
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)
{
- IntReleaseWindowObject(Window);
- RETURN( NULL);
+ RETURN(NULL);
}
if (Window->UpdateRegion != NULL)
{
MsqDecPaintCountQueue(Window->MessageQueue);
- IntValidateParent(Window, Window->UpdateRegion);
Rgn = RGNDATA_LockRgn(Window->UpdateRegion);
if (NULL != Rgn)
{
UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint);
RGNDATA_UnlockRgn(Rgn);
- IntGdiOffsetRect(&Ps.rcPaint,
- Window->WindowRect.left - Window->ClientRect.left,
- Window->WindowRect.top - Window->ClientRect.top);
+ IntGdiIntersectRect(&Ps.rcPaint, &Ps.rcPaint, &Window->ClientRect);
+ if (! IntGdiIsEmptyRect(&Ps.rcPaint))
+ {
+ IntGdiOffsetRect(&Ps.rcPaint,
+ -Window->ClientRect.left,
+ -Window->ClientRect.top);
+ }
}
else
{
IntGetClientRect(Window, &Ps.rcPaint);
}
GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
- NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
else
{
if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
MsqDecPaintCountQueue(Window->MessageQueue);
+
IntGetClientRect(Window, &Ps.rcPaint);
}
+
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
Ps.fErase = FALSE;
}
- IntReleaseWindowObject(Window);
-
Status = MmCopyToCaller(UnsafePs, &Ps, sizeof(PAINTSTRUCT));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
- RETURN( NULL);
+ RETURN(NULL);
}
- RETURN( Ps.hdc);
+ RETURN(Ps.hdc);
CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+
DPRINT("Leave NtUserBeginPaint, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
{
PWINDOW_OBJECT Window;
DECLARE_RETURN(BOOL);
+ USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserEndPaint\n");
UserEnterExclusive();
- if (!(Window = IntGetWindowObject(hWnd)))
+ if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(FALSE);
}
- UserReleaseDC(Window, lPs->hdc);
- co_UserShowCaret(Window);
+ UserReleaseDC(Window, lPs->hdc, TRUE);
- IntReleaseWindowObject(Window); //temp hack
+ UserRefObjectCo(Window, &Ref);
+ co_UserShowCaret(Window);
+ UserDerefObjectCo(Window);
RETURN(TRUE);
END_CLEANUP;
}
-/*
- * NtUserInvalidateRect
- *
- * Status
- * @implemented
- */
-
-DWORD STDCALL
-NtUserInvalidateRect(HWND hWnd, CONST RECT *Rect, BOOL Erase)
-{
- return NtUserRedrawWindow(hWnd, Rect, 0, RDW_INVALIDATE | (Erase ? RDW_ERASE : 0));
-}
-
-/*
- * NtUserInvalidateRgn
- *
- * Status
- * @implemented
- */
-
-DWORD STDCALL
-NtUserInvalidateRgn(HWND hWnd, HRGN Rgn, BOOL Erase)
-{
- return NtUserRedrawWindow(hWnd, NULL, Rgn, RDW_INVALIDATE | (Erase ? RDW_ERASE : 0));
-}
-
-
-
-BOOL FASTCALL
-co_UserValidateRgn(PWINDOW_OBJECT Window, HRGN hRgn)
-{
- return co_UserRedrawWindow(Window, NULL, hRgn, RDW_VALIDATE | RDW_NOCHILDREN);
-}
-
-/*
- * NtUserValidateRgn
- *
- * Status
- * @implemented
- */
-
-BOOL STDCALL
-NtUserValidateRgn(HWND hWnd, HRGN hRgn)
-{
- return NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_VALIDATE | RDW_NOCHILDREN);
-}
-
-/*
- * NtUserUpdateWindow
- *
- * Status
- * @implemented
- */
-
-BOOL STDCALL
-NtUserUpdateWindow(HWND hWnd)
-{
- return NtUserRedrawWindow(hWnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
-}
-
-
-
-
INT FASTCALL
co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase)
{
int RegionType;
+ RECT Rect;
ASSERT_REFS_CO(Window);
}
else
{
- RegionType = NtGdiCombineRgn(hRgn, Window->UpdateRegion, hRgn, RGN_COPY);
- NtGdiOffsetRgn(
- hRgn,
- Window->WindowRect.left - Window->ClientRect.left,
- Window->WindowRect.top - Window->ClientRect.top);
+ Rect = Window->ClientRect;
+ IntIntersectWithParents(Window, &Rect);
+ NtGdiSetRectRgn(hRgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
+ RegionType = NtGdiCombineRgn(hRgn, hRgn, Window->UpdateRegion, RGN_AND);
+ NtGdiOffsetRgn(hRgn, -Window->ClientRect.left, -Window->ClientRect.top);
}
if (bErase && RegionType != NULLREGION && RegionType != ERROR)
return RegionType;
}
+
/*
* NtUserGetUpdateRgn
*
DECLARE_RETURN(INT);
PWINDOW_OBJECT Window;
INT ret;
+ USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserGetUpdateRgn\n");
UserEnterExclusive();
RETURN(ERROR);
}
- UserRefObjectCo(Window);
+ UserRefObjectCo(Window, &Ref);
ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
UserDerefObjectCo(Window);
RECT Rect;
INT RegionType;
PROSRGNDATA RgnData;
- BOOL AlwaysPaint;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
if (!(Window = UserGetWindowObject(hWnd)))
{
- RETURN( ERROR);
+ RETURN(FALSE);
}
if (Window->UpdateRegion == NULL)
}
else
{
- RgnData = RGNDATA_LockRgn(Window->UpdateRegion);
- ASSERT(RgnData != NULL);
- RegionType = UnsafeIntGetRgnBox(RgnData, &Rect);
- ASSERT(RegionType != ERROR);
- RGNDATA_UnlockRgn(RgnData);
+ /* Get the update region bounding box. */
+ if (Window->UpdateRegion == (HRGN)1)
+ {
+ Rect = Window->ClientRect;
+ }
+ else
+ {
+ RgnData = RGNDATA_LockRgn(Window->UpdateRegion);
+ ASSERT(RgnData != NULL);
+ RegionType = UnsafeIntGetRgnBox(RgnData, &Rect);
+ RGNDATA_UnlockRgn(RgnData);
+
+ if (RegionType != ERROR && RegionType != NULLREGION)
+ IntGdiIntersectRect(&Rect, &Rect, &Window->ClientRect);
+ }
+
+ if (IntIntersectWithParents(Window, &Rect))
+ {
+ IntGdiOffsetRect(&Rect,
+ -Window->ClientRect.left,
+ -Window->ClientRect.top);
+ } else
+ {
+ Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
+ }
}
- AlwaysPaint = (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) ||
- (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT);
- if (bErase && Rect.left < Rect.right && Rect.top < Rect.bottom)
+ if (bErase && !IntGdiIsEmptyRect(&Rect))
{
- UserRefObjectCo(Window);
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(Window, &Ref);
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
UserDerefObjectCo(Window);
}
if (!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN( FALSE);
+ RETURN(FALSE);
}
}
- RETURN( (Rect.left < Rect.right && Rect.top < Rect.bottom) || AlwaysPaint);
+ RETURN(!IntGdiIsEmptyRect(&Rect));
CLEANUP:
DPRINT("Leave NtUserGetUpdateRect, ret=%i\n",_ret_);
NTSTATUS Status;
PWINDOW_OBJECT Wnd;
DECLARE_RETURN(BOOL);
+ USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserRedrawWindow\n");
UserEnterExclusive();
}
}
- UserRefObjectCo(Wnd);
+ UserRefObjectCo(Wnd, &Ref);
Status = co_UserRedrawWindow(Wnd, NULL == lprcUpdate ? NULL : &SafeUpdateRect,
hrgnUpdate, flags);
BOOL bOwnRgn = TRUE;
NTSTATUS Status;
DECLARE_RETURN(DWORD);
+ USER_REFERENCE_ENTRY Ref, CaretRef;
DPRINT("Enter NtUserScrollWindowEx\n");
UserEnterExclusive();
Window = NULL; /* prevent deref at cleanup */
RETURN( ERROR);
}
- UserRefObjectCo(Window);
+ UserRefObjectCo(Window, &Ref);
IntGetClientRect(Window, &rc);
if (hDC)
{
UserScrollDC(hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
- UserReleaseDC(Window, hDC);
+ UserReleaseDC(Window, hDC, FALSE);
}
/*
RECT r, dummy;
POINT ClientOrigin;
PWINDOW_OBJECT Wnd;
+ USER_REFERENCE_ENTRY WndRef;
IntGetClientOrigin(Window, &ClientOrigin);
for (i = 0; List[i]; i++)
if (! UnsafeRect || IntGdiIntersectRect(&dummy, &r, &rc))
{
- UserRefObjectCo(Wnd);
+ UserRefObjectCo(Wnd, &WndRef);
co_WinPosSetWindowPos(Wnd, 0, r.left + dx, r.top + dy, 0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
SWP_NOREDRAW);
if ((CaretWnd = UserGetWindowObject(hwndCaret)))
{
- UserRefObjectCo(CaretWnd);
+ UserRefObjectCo(CaretWnd, &CaretRef);
co_IntSetCaretPos(caretrc.left + dx, caretrc.top + dy);
co_UserShowCaret(CaretWnd);
UserDerefObjectCo(CaretWnd);
}
- RETURN( Result);
+ RETURN(Result);
CLEANUP:
if (Window)