* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: painting.c,v 1.57 2003/12/30 18:19:20 weiden Exp $
+ * $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES ******************************************************************/
-#include <ddk/ntddk.h>
-#include <internal/safe.h>
-#include <win32k/win32k.h>
-#include <include/object.h>
-#include <include/guicheck.h>
-#include <include/window.h>
-#include <include/desktop.h>
-#include <include/winpos.h>
-#include <include/class.h>
-#include <include/caret.h>
-#include <include/error.h>
-#include <include/winsta.h>
-#include <windows.h>
-#include <include/painting.h>
-#include <user32/wininternal.h>
-#include <include/rect.h>
-#include <win32k/coord.h>
-#include <win32k/region.h>
-#include <include/vis.h>
-#include <include/intgdi.h>
+#include <w32k.h>
#define NDEBUG
#include <debug.h>
-/* #define FIN_DEBUG */
-
/* PRIVATE FUNCTIONS **********************************************************/
-VOID FASTCALL
-IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
+/**
+ * @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)
{
- HWND Parent;
PWINDOW_OBJECT ParentWindow;
- Parent = NtUserGetAncestor(Child->Self, GA_PARENT);
- while (Parent && Parent != IntGetDesktopWindow())
+ ParentWindow = Child->Parent;
+ while (ParentWindow != NULL)
{
- ParentWindow = IntGetWindowObject(Parent);
- if (ParentWindow && !(ParentWindow->Style & WS_CLIPCHILDREN))
+ if (!(ParentWindow->Style & WS_VISIBLE) ||
+ (ParentWindow->Style & WS_MINIMIZE))
{
- if (ParentWindow->UpdateRegion != 0)
- {
- INT OffsetX, OffsetY;
+ return FALSE;
+ }
- /*
- * 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);
- }
+ if (!IntGdiIntersectRect(WindowRect, WindowRect, &ParentWindow->ClientRect))
+ {
+ return FALSE;
}
- IntReleaseWindowObject(ParentWindow);
- Parent = NtUserGetAncestor(Parent, GA_PARENT);
+
+ /* FIXME: Layered windows. */
+
+ ParentWindow = ParentWindow->Parent;
}
+
+ return TRUE;
}
-/*
- * IntGetNCUpdateRegion
- *
- * Get nonclient part of window update region.
- *
- * Return Value
- * Handle to region that represents invalid nonclient window area. The
- * caller is responsible for deleting it.
+VOID FASTCALL
+IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
+{
+ PWINDOW_OBJECT ParentWindow = Child->Parent;
+
+ while (ParentWindow)
+ {
+ if (ParentWindow->Style & WS_CLIPCHILDREN)
+ break;
+
+ if (ParentWindow->UpdateRegion != 0)
+ {
+ NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion,
+ ValidRegion, RGN_DIFF);
+ /* FIXME: If the resulting region is empty, remove fake posted paint message */
+ }
+
+ ParentWindow = ParentWindow->Parent;
+ }
+}
+
+/**
+ * @name IntCalcWindowRgn
*
- * Remarks
- * This function also marks the nonclient update region of window
- * as valid, clears the WINDOWOBJECT_NEED_NCPAINT flag.
+ * Get a window or client region.
*/
HRGN FASTCALL
-IntGetNCUpdateRegion(PWINDOW_OBJECT Window)
+IntCalcWindowRgn(PWINDOW_OBJECT Window, BOOL Client)
{
- HRGN WindowRgn;
- HRGN NonclientRgn;
+ HRGN hRgnWindow;
+ UINT RgnType;
- /*
- * Generate the update region.
- */
+ if (Client)
+ hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
+ else
+ hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
- WindowRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
- NtGdiOffsetRgn(WindowRgn,
- -Window->WindowRect.left,
- -Window->WindowRect.top);
- NonclientRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
- if (NtGdiCombineRgn(NonclientRgn, Window->UpdateRegion,
- WindowRgn, RGN_DIFF) == NULLREGION)
+ if (Window->WindowRegion != NULL && !(Window->Style & WS_MINIMIZE))
{
- NtGdiDeleteObject(NonclientRgn);
- NonclientRgn = NULL;
+ NtGdiOffsetRgn(hRgnWindow,
+ -Window->WindowRect.left,
+ -Window->WindowRect.top);
+ RgnType = NtGdiCombineRgn(hRgnWindow, hRgnWindow, Window->WindowRegion, RGN_AND);
+ NtGdiOffsetRgn(hRgnWindow,
+ Window->WindowRect.left,
+ Window->WindowRect.top);
}
- /*
- * Remove the nonclient region from the standard update region.
- */
+ return hRgnWindow;
+}
- if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
- WindowRgn, RGN_AND) == NULLREGION)
+/**
+ * @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)
{
- NtGdiDeleteObject(Window->UpdateRegion);
- Window->UpdateRegion = NULL;
- }
+ 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;
+ }
- return NonclientRgn;
+ /*
+ * 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;
+ }
}
/*
* Internal function used by IntRedrawWindow.
*/
-VOID FASTCALL
-IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
+STATIC VOID FASTCALL
+co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{
- HDC hDC;
- HWND hWnd = Window->Self;
+ HDC hDC;
+ HWND hWnd = Window->hSelf;
+ HRGN TempRegion;
- if (! (Window->Style & WS_VISIBLE))
- {
- return;
- }
-
- if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
- {
- if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
- {
- IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)Window->NCUpdateRegion, 0);
- Window->NCUpdateRegion = NULL;
- Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
- MsqDecPaintCountQueue(Window->MessageQueue);
- }
-
- if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
- {
- if (Window->UpdateRegion)
- {
-#ifdef FIN_DEBUG
- {
- RECT TempRect;
- UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
- DPRINT1("Sending WM_ERASEBKGND[1]: %d,%d-%d,%d\n",
- TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
- }
-#endif
- hDC = NtUserGetDCEx(hWnd, 0, DCX_CACHE | DCX_USESTYLE |
- DCX_INTERSECTUPDATE);
- if (hDC != NULL)
- {
- if (IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0))
- {
- Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBKGND;
- }
- NtUserReleaseDC(hWnd, hDC);
- }
- }
- }
+ if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
+ {
+ if (Window->UpdateRegion)
+ {
+ IntValidateParent(Window, Window->UpdateRegion);
+ }
if (Flags & RDW_UPDATENOW)
- {
- if (Window->UpdateRegion != NULL ||
- Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
+ {
+ if (Window->UpdateRegion != NULL ||
+ Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
+ {
+ co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
+ }
+ }
+ else
+ {
+ if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
+ {
+ 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)
{
-#ifdef FIN_DEBUG
- {
- RECT TempRect;
- UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
- DPRINT1("Sending WM_PAINT[1]: %d,%d-%d,%d\n",
- TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
- }
-#endif
- IntSendMessage(hWnd, WM_PAINT, 0, 0);
- if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
- {
- Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
- if (Window->UpdateRegion == NULL)
- {
- MsqDecPaintCountQueue(Window->MessageQueue);
- }
- }
+ /* NOTE: The region can already be deleted! */
+ GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
}
- }
- }
+ }
- /*
- * Check that the window is still valid at this point
- */
+ if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
+ {
+ 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, FALSE);
+ }
+ }
+ }
+ }
- if (! IntIsWindow(hWnd))
- {
+ /*
+ * Check that the window is still valid at this point
+ */
+ if (!IntIsWindow(hWnd))
+ {
return;
- }
-
- /*
- * Paint child windows.
- */
- if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
- ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)) &&
- ! IntIsDesktopWindow(Window))
- {
+ }
+
+ /*
+ * Paint child windows.
+ */
+ if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
+ ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)))
+ {
HWND *List, *phWnd;
if ((List = IntWinListChildren(Window)))
- {
- for (phWnd = List; *phWnd; ++phWnd)
+ {
+ for (phWnd = List; *phWnd; ++phWnd)
+ {
+ Window = UserGetWindowObject(*phWnd);
+ if (Window && (Window->Style & WS_VISIBLE))
{
- Window = IntGetWindowObject(*phWnd);
- if (Window)
- {
- IntPaintWindows(Window, Flags);
- IntReleaseWindowObject(Window);
- }
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(Window, &Ref);
+ co_IntPaintWindows(Window, Flags);
+ UserDerefObjectCo(Window);
}
- ExFreePool(List);
- }
- }
+ }
+ ExFreePool(List);
+ }
+ }
}
/*
*/
VOID FASTCALL
-IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags,
- BOOL ValidateParent)
+IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
{
INT RgnType;
BOOL HadPaintMessage, HadNCPaintMessage;
BOOL HasPaintMessage, HasNCPaintMessage;
- HRGN hRgnWindow;
/*
* Clip the given region with window rectangle (or region)
*/
-#ifdef TODO
- if (!Window->WindowRegion)
-#endif
+ if (!Window->WindowRegion || (Window->Style & WS_MINIMIZE))
{
+ HRGN hRgnWindow;
+
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);
}
-#ifdef TODO
else
{
- RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND);
+ NtGdiOffsetRgn(hRgn,
+ -Window->WindowRect.left,
+ -Window->WindowRect.top);
+ RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND);
+ NtGdiOffsetRgn(hRgn,
+ Window->WindowRect.left,
+ Window->WindowRect.top);
}
-#endif
/*
* Save current state of pending updates
*/
HadPaintMessage = Window->UpdateRegion != NULL ||
- Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
+ Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
HadNCPaintMessage = Window->Flags & WINDOWOBJECT_NEED_NCPAINT;
/*
if (Window->UpdateRegion == NULL)
{
Window->UpdateRegion = NtGdiCreateRectRgn(0, 0, 0, 0);
+ GDIOBJ_SetOwnership(Window->UpdateRegion, NULL);
}
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
- hRgn, RGN_OR) == NULLREGION)
+ hRgn, RGN_OR) == NULLREGION)
{
+ GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
if (Window->UpdateRegion != NULL)
{
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
- hRgn, RGN_DIFF) == NULLREGION)
+ hRgn, RGN_DIFF) == NULLREGION)
{
+ GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
}
- /*
- * Validate parent covered by region
- */
-
- if (ValidateParent)
- {
- IntValidateParent(Window, Window->UpdateRegion);
- }
-
- /*
- * Split the nonclient update region.
- */
-
- if (Window->NCUpdateRegion == NULL)
- {
- Window->NCUpdateRegion = IntGetNCUpdateRegion(Window);
- }
- else
- {
- HRGN hRgnNonClient = IntGetNCUpdateRegion(Window);
- NtGdiCombineRgn(Window->NCUpdateRegion, Window->NCUpdateRegion,
- hRgnNonClient, RGN_OR);
- NtGdiDeleteObject(hRgnNonClient);
- }
-
/*
* Process children if needed
*/
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;
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)
- {
- RECT TempRect;
-
- /*
- * 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, FALSE);
-
- /*
- * Update our UpdateRegion depending on children
- */
-
- if (Window->UpdateRegion != NULL)
- {
- UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
- NtGdiCombineRgn(hRgnTemp, Child->UpdateRegion, 0, RGN_COPY);
- NtGdiCombineRgn(hRgnTemp, hRgnTemp, Child->NCUpdateRegion, RGN_OR);
- NtGdiOffsetRgn(hRgnTemp,
- Child->WindowRect.left - Window->WindowRect.left,
- Child->WindowRect.top - Window->WindowRect.top);
- UnsafeIntGetRgnBox(hRgnTemp, &TempRect);
- if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
- hRgnTemp, RGN_DIFF) == NULLREGION)
- {
- NtGdiDeleteObject(Window->UpdateRegion);
- Window->UpdateRegion = NULL;
- }
- }
- 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);
+
}
}
/*
* Fake post paint messages to window message queue if needed
*/
+
HasPaintMessage = Window->UpdateRegion != NULL ||
- Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
+ Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
HasNCPaintMessage = Window->Flags & WINDOWOBJECT_NEED_NCPAINT;
if (HasPaintMessage != HadPaintMessage)
else
MsqIncPaintCountQueue(Window->MessageQueue);
}
+
}
/*
BOOL FASTCALL
IntIsWindowDrawable(PWINDOW_OBJECT Window)
{
- PWINDOW_OBJECT Wnd = Window;
-
- for (; Wnd; Wnd = Wnd->Parent)
+ PWINDOW_OBJECT Wnd;
+
+ for (Wnd = Window; Wnd != NULL; Wnd = Wnd->Parent)
{
if (!(Wnd->Style & WS_VISIBLE) ||
- ((Wnd->Style & WS_MINIMIZE) && (Wnd != Window)))
+ ((Wnd->Style & WS_MINIMIZE) && (Wnd != Window)))
+ {
return FALSE;
+ }
}
return TRUE;
*/
BOOL FASTCALL
-IntRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRgn,
- ULONG Flags)
+co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRgn,
+ ULONG Flags)
{
HRGN hRgn = NULL;
*/
if (!IntIsWindowDrawable(Window) ||
- (Flags & (RDW_VALIDATE | RDW_INVALIDATE)) ==
- (RDW_VALIDATE | RDW_INVALIDATE))
+ (Flags & (RDW_VALIDATE | RDW_INVALIDATE)) ==
+ (RDW_VALIDATE | RDW_INVALIDATE))
{
return FALSE;
}
/*
* 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);
- } else
- if (UpdateRect != NULL)
+ if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
+ NtGdiDeleteObject(hRgn);
+ else
+ NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top);
+ }
+ else if (UpdateRect != NULL)
{
- hRgn = UnsafeIntCreateRectRgnIndirect((RECT *)UpdateRect);
- NtGdiOffsetRgn(hRgn,
- Window->ClientRect.left - Window->WindowRect.left,
- Window->ClientRect.top - 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(UpdateRect))
+ {
+ hRgn = UnsafeIntCreateRectRgnIndirect((RECT *)UpdateRect);
+ 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);
+ if (!IntGdiIsEmptyRect(&Window->WindowRect))
+ hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
}
else
{
- hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
- NtGdiOffsetRgn(hRgn,
- -Window->WindowRect.left,
- -Window->WindowRect.top);
+ 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))
- {
- IntInvalidateWindows(Window, hRgn, Flags, TRUE);
- } else
- if (Window->UpdateRegion != NULL && Flags & RDW_ERASENOW)
+ if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) &&
+ hRgn != NULL)
{
- /* Validate parent covered by region. */
- IntValidateParent(Window, Window->UpdateRegion);
+ IntInvalidateWindows(Window, hRgn, Flags);
}
/*
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{
- IntPaintWindows(Window, Flags);
+ co_IntPaintWindows(Window, Flags);
}
/*
* Cleanup ;-)
*/
- if (NULL != hRgn)
+ if (hRgn != NULL)
{
NtGdiDeleteObject(hRgn);
}
return TRUE;
}
-HWND STDCALL
-IntFindWindowToRepaint(HWND hWnd, PW32THREAD Thread)
+BOOL FASTCALL
+IntIsWindowDirty(PWINDOW_OBJECT Window)
{
- PWINDOW_OBJECT Window;
- PWINDOW_OBJECT Child;
- HWND hFoundWnd = NULL;
-
- if (hWnd == NULL)
- {
- PLIST_ENTRY CurrentEntry;
+ return (Window->Style & WS_VISIBLE) &&
+ ((Window->UpdateRegion != NULL) ||
+ (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT) ||
+ (Window->Flags & WINDOWOBJECT_NEED_NCPAINT));
+}
- ExAcquireFastMutex(&Thread->WindowListLock);
+HWND FASTCALL
+IntFindWindowToRepaint(PWINDOW_OBJECT Window, PW32THREAD Thread)
+{
+ HWND hChild;
+ PWINDOW_OBJECT TempWindow;
- for (CurrentEntry = Thread->WindowListHead.Flink;
- CurrentEntry != &Thread->WindowListHead;
- CurrentEntry = CurrentEntry->Flink)
+ for (; Window != NULL; Window = Window->NextSibling)
+ {
+ if (IntWndBelongsToThread(Window, Thread) &&
+ IntIsWindowDirty(Window))
{
- Window = CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, ThreadListEntry);
- if (Window->Parent != NULL && !IntIsDesktopWindow(Window->Parent))
+ /* Make sure all non-transparent siblings are already drawn. */
+ if (Window->ExStyle & WS_EX_TRANSPARENT)
{
- continue;
- }
- if (Window->Style & WS_VISIBLE)
- {
- hFoundWnd = IntFindWindowToRepaint(Window->Self, Thread);
- if (hFoundWnd != NULL)
+ for (TempWindow = Window->NextSibling; TempWindow != NULL;
+ TempWindow = TempWindow->NextSibling)
{
- ExReleaseFastMutex(&Thread->WindowListLock);
- return hFoundWnd;
+ if (!(TempWindow->ExStyle & WS_EX_TRANSPARENT) &&
+ IntWndBelongsToThread(TempWindow, Thread) &&
+ IntIsWindowDirty(TempWindow))
+ {
+ return TempWindow->hSelf;
+ }
}
}
- }
-
- ExReleaseFastMutex(&Thread->WindowListLock);
- return NULL;
- }
- else
- {
- Window = IntGetWindowObject(hWnd);
- if (Window == NULL)
- return NULL;
- if ((Window->UpdateRegion != NULL ||
- Window->Flags & (WINDOWOBJECT_NEED_INTERNALPAINT | WINDOWOBJECT_NEED_NCPAINT)) &&
- IntWndBelongsToThread(Window, Thread))
- {
- IntReleaseWindowObject(Window);
- return hWnd;
+ return Window->hSelf;
}
- ExAcquireFastMutex(&Window->ChildrenListLock);
-
- for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
+ if (Window->FirstChild)
{
- if (Child->Style & WS_VISIBLE &&
- (Child->UpdateRegion != NULL ||
- Child->Flags & WINDOWOBJECT_NEED_INTERNALPAINT ||
- Child->Flags & WINDOWOBJECT_NEED_NCPAINT)
- && IntWndBelongsToThread(Child, Thread))
- {
- hFoundWnd = Child->Self;
- break;
- }
+ hChild = IntFindWindowToRepaint(Window->FirstChild, Thread);
+ if (hChild != NULL)
+ return hChild;
}
-
- if (hFoundWnd == NULL)
- {
- for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
- {
- if (Child->Style & WS_VISIBLE)
- {
- hFoundWnd = IntFindWindowToRepaint(Child->Self, Thread);
- if (hFoundWnd != NULL)
- break;
- }
- }
- }
-
- ExReleaseFastMutex(&Window->ChildrenListLock);
- IntReleaseWindowObject(Window);
-
- return hFoundWnd;
}
+
+ return NULL;
}
BOOL FASTCALL
-IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message,
- BOOL Remove)
+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 (hWnd)
- Message->hwnd = IntFindWindowToRepaint(hWnd, PsGetWin32Thread());
- else
- Message->hwnd = IntFindWindowToRepaint(NULL, PsGetWin32Thread());
+ if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
+ (MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
+ return FALSE;
+
+ Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetWin32Thread());
if (Message->hwnd == NULL)
{
-#if 0
DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
- /* FIXME: Lock the queue! */
- MessageQueue->PaintPosted = 0;
- MessageQueue->PaintCount = 0;
-#endif
return FALSE;
}
- Window = IntGetWindowObject(Message->hwnd);
- if (Window != NULL)
- {
- if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
- {
- Message->message = WM_NCPAINT;
- Message->wParam = (WPARAM)Window->NCUpdateRegion;
- Message->lParam = 0;
- if (Remove)
- {
- Window->NCUpdateRegion = NULL;
- Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
- MsqDecPaintCountQueue(Window->MessageQueue);
- }
- } else
- {
-#ifdef FIN_DEBUG
- {
- RECT TempRect;
- UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
- DPRINT1("Sending WM_PAINT[2]: %d,%d-%d,%d\n",
- TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
- }
-#endif
- Message->message = WM_PAINT;
- Message->wParam = Message->lParam = 0;
- if (Remove && Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
- {
- Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
- if (Window->UpdateRegion == NULL)
- {
- MsqDecPaintCountQueue(Window->MessageQueue);
- }
- }
- }
+ if (hWnd != NULL && Message->hwnd != hWnd)
+ return FALSE;
- IntReleaseWindowObject(Window);
- return TRUE;
- }
+ Message->message = WM_PAINT;
+ Message->wParam = Message->lParam = 0;
- return FALSE;
+ return TRUE;
}
+static
HWND FASTCALL
-IntFixCaret(HWND hWnd, LPRECT lprc, UINT flags)
+co_IntFixCaret(PWINDOW_OBJECT Window, LPRECT lprc, UINT flags)
{
- GUITHREADINFO info;
-
- if (!NtUserGetGUIThreadInfo(0, &info))
- return 0;
- if (!info.hwndCaret)
- return 0;
- if (info.hwndCaret == hWnd ||
- ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(hWnd, info.hwndCaret)))
+ PDESKTOP_OBJECT Desktop;
+ PTHRDCARETINFO CaretInfo;
+ HWND hWndCaret;
+ PWINDOW_OBJECT WndCaret;
+
+ ASSERT_REFS_CO(Window);
+
+ 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, WndCaret)))
{
POINT pt, FromOffset, ToOffset, Offset;
-
- pt.x = info.rcCaret.left;
- pt.y = info.rcCaret.top;
+ RECT rcCaret;
- IntGetClientOrigin(info.hwndCaret, &FromOffset);
- IntGetClientOrigin(hWnd, &ToOffset);
+ pt.x = CaretInfo->Pos.x;
+ pt.y = CaretInfo->Pos.y;
+ IntGetClientOrigin(WndCaret, &FromOffset);
+ IntGetClientOrigin(Window, &ToOffset);
Offset.x = FromOffset.x - ToOffset.x;
Offset.y = FromOffset.y - ToOffset.y;
- info.rcCaret.left += Offset.x;
- info.rcCaret.top += Offset.y;
- info.rcCaret.right += Offset.x;
- info.rcCaret.bottom += Offset.y;
- if (NtGdiIntersectRect(lprc, lprc, &info.rcCaret))
+ rcCaret.left = pt.x;
+ rcCaret.top = pt.y;
+ rcCaret.right = pt.x + CaretInfo->Size.cx;
+ rcCaret.bottom = pt.y + CaretInfo->Size.cy;
+ if (IntGdiIntersectRect(lprc, lprc, &rcCaret))
{
- NtUserHideCaret(0);
+ co_UserHideCaret(0);
lprc->left = pt.x;
lprc->top = pt.y;
- return info.hwndCaret;
+ return hWndCaret;
}
}
*/
HDC STDCALL
-NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs)
+NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
{
- PWINDOW_OBJECT Window;
- RECT ClientRect;
- RECT ClipRect;
- INT DcxFlags;
+ 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;
+ RETURN( NULL);
}
- NtUserHideCaret(hWnd);
-
- DcxFlags = DCX_INTERSECTUPDATE | DCX_WINDOWPAINT | DCX_USESTYLE;
+ UserRefObjectCo(Window, &Ref);
- lPs->hdc = NtUserGetDCEx(hWnd, 0, DcxFlags);
+ co_UserHideCaret(Window);
- if (!lPs->hdc)
+ if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
- IntReleaseWindowObject(Window);
- return NULL;
+ HRGN hRgn;
+
+ hRgn = IntGetNCUpdateRgn(Window, FALSE);
+ Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
+ MsqDecPaintCountQueue(Window->MessageQueue);
+ co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
+ if (hRgn != (HANDLE)1 && hRgn != NULL)
+ {
+ /* NOTE: The region can already by deleted! */
+ GDIOBJ_FreeObj(hRgn, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
+ }
}
-/* IntRedrawWindow(Window, NULL, 0, RDW_NOINTERNALPAINT | RDW_VALIDATE | RDW_NOCHILDREN);*/
-#ifdef FIN_DEBUG
- if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
+ RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT));
+
+ Ps.hdc = UserGetDCEx(Window, Window->UpdateRegion, DCX_INTERSECTRGN | DCX_USESTYLE);
+ if (!Ps.hdc)
{
- RECT TempRect;
- UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
- DPRINT1("Sending WM_ERASEBKGND[2]: %d,%d-%d,%d\n",
- TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
+ RETURN(NULL);
}
-#endif
-
+
if (Window->UpdateRegion != NULL)
{
MsqDecPaintCountQueue(Window->MessageQueue);
- IntValidateParent(Window, Window->UpdateRegion);
- NtGdiDeleteObject(Window->UpdateRegion);
+ Rgn = RGNDATA_LockRgn(Window->UpdateRegion);
+ if (NULL != Rgn)
+ {
+ UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint);
+ RGNDATA_UnlockRgn(Rgn);
+ IntGdiIntersectRect(&Ps.rcPaint, &Ps.rcPaint, &Window->ClientRect);
+ IntGdiOffsetRect(&Ps.rcPaint,
+ -Window->ClientRect.left,
+ -Window->ClientRect.top);
+ }
+ else
+ {
+ IntGetClientRect(Window, &Ps.rcPaint);
+ }
+ GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess());
Window->UpdateRegion = NULL;
}
+ else
+ {
+ if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
+ MsqDecPaintCountQueue(Window->MessageQueue);
+
+ IntGetClientRect(Window, &Ps.rcPaint);
+ }
- IntGetClientRect(Window, &ClientRect);
- IntGdiGetClipBox(lPs->hdc, &ClipRect);
- NtGdiLPtoDP(lPs->hdc, (LPPOINT)&ClipRect, 2);
- NtGdiIntersectRect(&lPs->rcPaint, &ClientRect, &ClipRect);
- NtGdiDPtoLP(lPs->hdc, (LPPOINT)&lPs->rcPaint, 2);
+ Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
{
Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBKGND;
- lPs->fErase = !IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)lPs->hdc, 0);
+ Ps.fErase = !co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)Ps.hdc, 0);
}
else
{
- lPs->fErase = FALSE;
+ Ps.fErase = FALSE;
+ }
+
+ Status = MmCopyToCaller(UnsafePs, &Ps, sizeof(PAINTSTRUCT));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(NULL);
}
- IntReleaseWindowObject(Window);
+ RETURN(Ps.hdc);
+
+CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+
+ DPRINT("Leave NtUserBeginPaint, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
- return lPs->hdc;
}
/*
BOOL STDCALL
NtUserEndPaint(HWND hWnd, CONST PAINTSTRUCT* lPs)
{
- NtUserReleaseDC(hWnd, lPs->hdc);
- NtUserShowCaret(hWnd);
+ PWINDOW_OBJECT Window;
+ DECLARE_RETURN(BOOL);
+ USER_REFERENCE_ENTRY Ref;
- return TRUE;
-}
+ DPRINT("Enter NtUserEndPaint\n");
+ UserEnterExclusive();
-/*
- * NtUserInvalidateRect
- *
- * Status
- * @implemented
- */
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(FALSE);
+ }
-DWORD STDCALL
-NtUserInvalidateRect(HWND hWnd, CONST RECT *Rect, BOOL Erase)
-{
- return NtUserRedrawWindow(hWnd, Rect, 0, RDW_INVALIDATE | (Erase ? RDW_ERASE : 0));
-}
+ UserReleaseDC(Window, lPs->hdc, TRUE);
-/*
- * NtUserInvalidateRgn
- *
- * Status
- * @implemented
- */
+ UserRefObjectCo(Window, &Ref);
+ co_UserShowCaret(Window);
+ UserDerefObjectCo(Window);
-DWORD STDCALL
-NtUserInvalidateRgn(HWND hWnd, HRGN Rgn, BOOL Erase)
-{
- return NtUserRedrawWindow(hWnd, NULL, Rgn, RDW_INVALIDATE | (Erase ? RDW_ERASE : 0));
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserEndPaint, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
-/*
- * NtUserValidateRgn
- *
- * Status
- * @implemented
- */
-BOOL STDCALL
-NtUserValidateRgn(HWND hWnd, HRGN hRgn)
+INT FASTCALL
+co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase)
{
- return NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_VALIDATE | RDW_NOCHILDREN);
-}
+ int RegionType;
+ RECT Rect;
-/*
- * NtUserUpdateWindow
- *
- * Status
- * @implemented
- */
-
-BOOL STDCALL
-NtUserUpdateWindow(HWND hWnd)
-{
- return NtUserRedrawWindow(hWnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
+ ASSERT_REFS_CO(Window);
+
+ if (Window->UpdateRegion == NULL)
+ {
+ RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
+ }
+ else
+ {
+ 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)
+ {
+ co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
+ }
+
+ return RegionType;
}
/*
INT STDCALL
NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
{
+ DECLARE_RETURN(INT);
PWINDOW_OBJECT Window;
- int RegionType;
+ INT ret;
+ USER_REFERENCE_ENTRY Ref;
- if (!(Window = IntGetWindowObject(hWnd)))
- {
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return ERROR;
- }
-
- if (Window->UpdateRegion == NULL)
- {
- RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
- }
- else
+ DPRINT("Enter NtUserGetUpdateRgn\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
{
- RegionType = NtGdiCombineRgn(hRgn, Window->UpdateRegion, hRgn, RGN_COPY);
- NtGdiOffsetRgn(
- hRgn,
- Window->WindowRect.left - Window->ClientRect.left,
- Window->WindowRect.top - Window->ClientRect.top);
+ RETURN(ERROR);
}
- IntReleaseWindowObject(Window);
+ UserRefObjectCo(Window, &Ref);
+ ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
+ UserDerefObjectCo(Window);
- if (bErase && RegionType != NULLREGION && RegionType != ERROR)
- {
- NtUserRedrawWindow(hWnd, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
- }
-
- return RegionType;
+ RETURN(ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
*/
BOOL STDCALL
-NtUserGetUpdateRect(HWND hWnd, LPRECT lpRect, BOOL fErase)
+NtUserGetUpdateRect(HWND hWnd, LPRECT UnsafeRect, BOOL bErase)
{
- HRGN hRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+ PWINDOW_OBJECT Window;
+ RECT Rect;
+ INT RegionType;
+ PROSRGNDATA RgnData;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetUpdateRect\n");
+ UserEnterExclusive();
- if (!lpRect)
+ if (!(Window = UserGetWindowObject(hWnd)))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
+ RETURN(FALSE);
+ }
+
+ if (Window->UpdateRegion == NULL)
+ {
+ Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
+ }
+ else
+ {
+ /* 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;
+ }
}
- NtUserGetUpdateRgn(hWnd, hRgn, fErase);
- NtGdiGetRgnBox(hRgn, lpRect);
+ if (bErase && !IntGdiIsEmptyRect(&Rect))
+ {
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(Window, &Ref);
+ co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
+ UserDerefObjectCo(Window);
+ }
- return lpRect->left < lpRect->right && lpRect->top < lpRect->bottom;
+ if (UnsafeRect != NULL)
+ {
+ Status = MmCopyToCaller(UnsafeRect, &Rect, sizeof(RECT));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(FALSE);
+ }
+ }
+
+ RETURN(Window->UpdateRegion != NULL);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetUpdateRect, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
BOOL STDCALL
NtUserRedrawWindow(HWND hWnd, CONST RECT *lprcUpdate, HRGN hrgnUpdate,
- UINT flags)
+ UINT flags)
{
RECT SafeUpdateRect;
NTSTATUS Status;
PWINDOW_OBJECT Wnd;
+ DECLARE_RETURN(BOOL);
+ USER_REFERENCE_ENTRY Ref;
+
+ DPRINT("Enter NtUserRedrawWindow\n");
+ UserEnterExclusive();
- if (!(Wnd = IntGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
+ if (!(Wnd = UserGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
{
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
+ RETURN( FALSE);
}
if (lprcUpdate != NULL)
{
Status = MmCopyFromCaller(&SafeUpdateRect, (PRECT)lprcUpdate,
- sizeof(RECT));
+ sizeof(RECT));
if (!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
+ RETURN( FALSE);
}
}
- Status = IntRedrawWindow(Wnd, NULL == lprcUpdate ? NULL : &SafeUpdateRect,
- hrgnUpdate, flags);
+ UserRefObjectCo(Wnd, &Ref);
+
+ Status = co_UserRedrawWindow(Wnd, NULL == lprcUpdate ? NULL : &SafeUpdateRect,
+ hrgnUpdate, flags);
+
+ UserDerefObjectCo(Wnd);
if (!NT_SUCCESS(Status))
{
/* IntRedrawWindow fails only in case that flags are invalid */
SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
+ RETURN( FALSE);
}
-
- return TRUE;
+
+ RETURN( TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
-/*
- * NtUserScrollDC
- *
- * Status
- * @implemented
- */
-DWORD STDCALL
-NtUserScrollDC(HDC hDC, INT dx, INT dy, const RECT *lprcScroll,
- const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
+
+static
+DWORD FASTCALL
+UserScrollDC(HDC hDC, INT dx, INT dy, const RECT *lprcScroll,
+ const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
{
RECT rSrc, rClipped_src, rClip, rDst, offset;
+ PDC DC;
/*
* Compute device clipping region (in device coordinates).
*/
+ DC = DC_LockDc(hDC);
+ if (NULL == DC)
+ {
+ return FALSE;
+ }
if (lprcScroll)
rSrc = *lprcScroll;
else
IntGdiGetClipBox(hDC, &rSrc);
- NtGdiLPtoDP(hDC, (LPPOINT)&rSrc, 2);
+ IntLPtoDP(DC, (LPPOINT)&rSrc, 2);
if (lprcClip)
rClip = *lprcClip;
else
IntGdiGetClipBox(hDC, &rClip);
- NtGdiLPtoDP(hDC, (LPPOINT)&rClip, 2);
+ IntLPtoDP(DC, (LPPOINT)&rClip, 2);
- NtGdiIntersectRect(&rClipped_src, &rSrc, &rClip);
+ IntGdiIntersectRect(&rClipped_src, &rSrc, &rClip);
rDst = rClipped_src;
- NtGdiSetRect(&offset, 0, 0, dx, dy);
- NtGdiLPtoDP(hDC, (LPPOINT)&offset, 2);
- NtGdiOffsetRect(&rDst, offset.right - offset.left, offset.bottom - offset.top);
- NtGdiIntersectRect(&rDst, &rDst, &rClip);
+ IntGdiSetRect(&offset, 0, 0, dx, dy);
+ IntLPtoDP(DC, (LPPOINT)&offset, 2);
+ IntGdiOffsetRect(&rDst, offset.right - offset.left, offset.bottom - offset.top);
+ IntGdiIntersectRect(&rDst, &rDst, &rClip);
/*
* Copy bits, if possible.
{
RECT rDst_lp = rDst, rSrc_lp = rDst;
- NtGdiOffsetRect(&rSrc_lp, offset.left - offset.right, offset.top - offset.bottom);
- NtGdiDPtoLP(hDC, (LPPOINT)&rDst_lp, 2);
- NtGdiDPtoLP(hDC, (LPPOINT)&rSrc_lp, 2);
+ IntGdiOffsetRect(&rSrc_lp, offset.left - offset.right, offset.top - offset.bottom);
+ IntDPtoLP(DC, (LPPOINT)&rDst_lp, 2);
+ IntDPtoLP(DC, (LPPOINT)&rSrc_lp, 2);
+ DC_UnlockDc(DC);
if (!NtGdiBitBlt(hDC, rDst_lp.left, rDst_lp.top, rDst_lp.right - rDst_lp.left,
rDst_lp.bottom - rDst_lp.top, hDC, rSrc_lp.left, rSrc_lp.top,
SRCCOPY))
return FALSE;
}
+ else
+ {
+ DC_UnlockDc(DC);
+ }
/*
* Compute update areas. This is the clipped source or'ed with the
else
hRgn = NtGdiCreateRectRgn(rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom);
- hRgn2 = NtGdiCreateRectRgnIndirect(&rSrc);
+ hRgn2 = UnsafeIntCreateRectRgnIndirect(&rSrc);
NtGdiOffsetRgn(hRgn2, offset.right - offset.left, offset.bottom - offset.top);
NtGdiCombineRgn(hRgn, hRgn, hRgn2, RGN_OR);
NtGdiSetRectRgn(hRgn2, rDst.left, rDst.top, rDst.right, rDst.bottom);
NtGdiCombineRgn(hRgn, hRgn, hRgn2, RGN_DIFF);
-
+
NtGdiSetRectRgn(hRgn2, rClip.left, rClip.top, rClip.right, rClip.bottom);
NtGdiCombineRgn(hRgn, hRgn, hRgn2, RGN_AND);
return TRUE;
}
+
+
+
+/*
+ * NtUserScrollDC
+ *
+ * Status
+ * @implemented
+ */
+
+DWORD STDCALL
+NtUserScrollDC(HDC hDC, INT dx, INT dy, const RECT *lprcScroll,
+ const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
+{
+ DECLARE_RETURN(DWORD);
+
+ DPRINT("Enter NtUserScrollDC\n");
+ UserEnterExclusive();
+
+ RETURN( UserScrollDC(hDC, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate));
+
+CLEANUP:
+ DPRINT("Leave NtUserScrollDC, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+
+}
+
/*
* NtUserScrollWindowEx
*
*/
DWORD STDCALL
-NtUserScrollWindowEx(HWND hWnd, INT dx, INT dy, const RECT *rect,
- const RECT *clipRect, HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags)
+NtUserScrollWindowEx(HWND hWnd, INT dx, INT dy, const RECT *UnsafeRect,
+ const RECT *UnsafeClipRect, HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags)
{
- RECT rc, cliprc, caretrc;
+ RECT rc, cliprc, caretrc, rect, clipRect;
INT Result;
- PWINDOW_OBJECT Window;
+ PWINDOW_OBJECT Window = NULL, CaretWnd;
HDC hDC;
HRGN hrgnTemp;
HWND hwndCaret;
BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
BOOL bOwnRgn = TRUE;
+ NTSTATUS Status;
+ DECLARE_RETURN(DWORD);
+ USER_REFERENCE_ENTRY Ref, CaretRef;
- Window = IntGetWindowObject(hWnd);
+ DPRINT("Enter NtUserScrollWindowEx\n");
+ UserEnterExclusive();
+
+ Window = UserGetWindowObject(hWnd);
if (!Window || !IntIsWindowDrawable(Window))
{
- IntReleaseWindowObject(Window);
- return ERROR;
+ Window = NULL; /* prevent deref at cleanup */
+ RETURN( ERROR);
}
+ UserRefObjectCo(Window, &Ref);
IntGetClientRect(Window, &rc);
- if (rect)
- NtGdiIntersectRect(&rc, &rc, rect);
- if (clipRect)
- NtGdiIntersectRect(&cliprc, &rc, clipRect);
+ if (NULL != UnsafeRect)
+ {
+ Status = MmCopyFromCaller(&rect, UnsafeRect, sizeof(RECT));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( ERROR);
+ }
+ IntGdiIntersectRect(&rc, &rc, &rect);
+ }
+
+ if (NULL != UnsafeClipRect)
+ {
+ Status = MmCopyFromCaller(&clipRect, UnsafeClipRect, sizeof(RECT));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( ERROR);
+ }
+ IntGdiIntersectRect(&cliprc, &rc, &clipRect);
+ }
else
cliprc = rc;
if (cliprc.right <= cliprc.left || cliprc.bottom <= cliprc.top ||
- (dx == 0 && dy == 0))
- {
- return NULLREGION;
+ (dx == 0 && dy == 0))
+ {
+ RETURN( NULLREGION);
}
caretrc = rc;
- hwndCaret = IntFixCaret(hWnd, &caretrc, flags);
+ hwndCaret = co_IntFixCaret(Window, &caretrc, flags);
if (hrgnUpdate)
bOwnRgn = FALSE;
else if (bUpdate)
hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
- hDC = NtUserGetDCEx( hWnd, 0, DCX_CACHE | DCX_USESTYLE );
+ hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE);
if (hDC)
{
- HRGN hRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
-
- NtUserScrollDC(hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
- NtUserReleaseDC(hWnd, hDC);
- if (bUpdate)
- NtGdiCombineRgn(hrgnUpdate, hrgnUpdate, hRgn, RGN_OR);
- else
- NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_INVALIDATE | RDW_ERASE);
- NtGdiDeleteObject(hRgn);
+ UserScrollDC(hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
+ UserReleaseDC(Window, hDC, FALSE);
}
- /*
+ /*
* Take into account the fact that some damage may have occurred during
* the scroll.
*/
hrgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
- Result = NtUserGetUpdateRgn(hWnd, hrgnTemp, FALSE);
+ Result = co_UserGetUpdateRgn(Window, hrgnTemp, FALSE);
if (Result != NULLREGION)
{
- HRGN hrgnClip = NtGdiCreateRectRgnIndirect(&cliprc);
+ HRGN hrgnClip = UnsafeIntCreateRectRgnIndirect(&cliprc);
NtGdiOffsetRgn(hrgnTemp, dx, dy);
NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnClip, RGN_AND);
- NtUserRedrawWindow(hWnd, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE);
+ co_UserRedrawWindow(Window, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE);
NtGdiDeleteObject(hrgnClip);
}
+
NtGdiDeleteObject(hrgnTemp);
if (flags & SW_SCROLLCHILDREN)
int i;
RECT r, dummy;
POINT ClientOrigin;
+ PWINDOW_OBJECT Wnd;
+ USER_REFERENCE_ENTRY WndRef;
+ IntGetClientOrigin(Window, &ClientOrigin);
for (i = 0; List[i]; i++)
{
- NtUserGetWindowRect(List[i], &r);
- IntGetClientOrigin(hWnd, &ClientOrigin);
+ if (!(Wnd = UserGetWindowObject(List[i])))
+ continue;
+
+ r = Wnd->WindowRect;
r.left -= ClientOrigin.x;
r.top -= ClientOrigin.y;
r.right -= ClientOrigin.x;
r.bottom -= ClientOrigin.y;
- if (!rect || NtGdiIntersectRect(&dummy, &r, &rc))
- WinPosSetWindowPos(List[i], 0, r.left + dx, r.top + dy, 0, 0,
- SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
- SWP_NOREDRAW);
+
+ if (! UnsafeRect || IntGdiIntersectRect(&dummy, &r, &rc))
+ {
+ UserRefObjectCo(Wnd, &WndRef);
+ co_WinPosSetWindowPos(Wnd, 0, r.left + dx, r.top + dy, 0, 0,
+ SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
+ SWP_NOREDRAW);
+ UserDerefObjectCo(Wnd);
+ }
+
}
ExFreePool(List);
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
- NtUserRedrawWindow(hWnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
- ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
- ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
+ co_UserRedrawWindow(Window, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
+ ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
+ ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
if (bOwnRgn && hrgnUpdate)
NtGdiDeleteObject(hrgnUpdate);
-
- if (hwndCaret)
+
+ if ((CaretWnd = UserGetWindowObject(hwndCaret)))
{
- IntSetCaretPos(caretrc.left + dx, caretrc.top + dy);
- NtUserShowCaret(hwndCaret);
+ UserRefObjectCo(CaretWnd, &CaretRef);
+
+ co_IntSetCaretPos(caretrc.left + dx, caretrc.top + dy);
+ co_UserShowCaret(CaretWnd);
+
+ UserDerefObjectCo(CaretWnd);
}
- IntReleaseWindowObject(Window);
-
- return Result;
+ RETURN(Result);
+
+CLEANUP:
+ if (Window)
+ UserDerefObjectCo(Window);
+
+ DPRINT("Leave NtUserScrollWindowEx, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/* EOF */