if (Wnd->hrgnUpdate != NULL ||
Wnd->state & WNDS_INTERNALPAINT)
{
+ Wnd->state2 |= WNDS2_WMPAINTSENT;
co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
}
}
{
TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
Wnd->state &= ~WNDS_SENDNCPAINT;
- MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
-
}
if (Wnd->state & WNDS_SENDERASEBACKGROUND)
IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
{
INT RgnType;
- BOOL HadPaintMessage, HadNCPaintMessage;
- BOOL HasPaintMessage, HasNCPaintMessage;
+ BOOL HadPaintMessage;
TRACE("IntInvalidateWindows start\n");
+
/*
* If the nonclient is not to be redrawn, clip the region to the client
* rect
* Save current state of pending updates
*/
- HadPaintMessage = Wnd->hrgnUpdate != NULL ||
- Wnd->state & WNDS_INTERNALPAINT;
- HadNCPaintMessage = Wnd->state & WNDS_SENDNCPAINT;
+ HadPaintMessage = IntIsWindowDirty(Wnd);
/*
* Update the region and flags
*/
- if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
+ // The following flags are used to invalidate the window.
+ if (Flags & (RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_ERASE|RDW_FRAME))
{
- if (Wnd->hrgnUpdate == NULL)
+ if (Flags & RDW_INTERNALPAINT)
{
- Wnd->hrgnUpdate = IntSysCreateRectRgn(0, 0, 0, 0);
- IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+ Wnd->state |= WNDS_INTERNALPAINT;
}
- if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
- hRgn, RGN_OR) == NULLREGION)
+ if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
{
- IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(Wnd->hrgnUpdate);
- Wnd->hrgnUpdate = NULL;
- }
+ /* If not the same thread set it dirty. */
+ if (Wnd->head.pti != PsGetCurrentThreadWin32Thread())
+ {
+ Wnd->state |= WNDS_UPDATEDIRTY;
+ }
- if (Flags & RDW_FRAME)
- Wnd->state |= WNDS_SENDNCPAINT;
- if (Flags & RDW_ERASE)
- Wnd->state |= WNDS_SENDERASEBACKGROUND;
+ if (Flags & RDW_FRAME)
+ Wnd->state |= WNDS_SENDNCPAINT;
+ if (Flags & RDW_ERASE)
+ Wnd->state |= WNDS_SENDERASEBACKGROUND;
- Flags |= RDW_FRAME;
- }
+ if (Wnd->hrgnUpdate == NULL)
+ {
+ Wnd->hrgnUpdate = IntSysCreateRectRgn(0, 0, 0, 0);
+ IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+ }
- if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
- {
- if (Wnd->hrgnUpdate != NULL)
- {
if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
- hRgn, RGN_DIFF) == NULLREGION)
+ hRgn, RGN_OR) == NULLREGION)
{
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL;
}
+ Flags |= RDW_FRAME; // For children.
}
+ } // The following flags are used to validate the window.
+ else if (Flags & (RDW_VALIDATE|RDW_NOINTERNALPAINT|RDW_NOERASE|RDW_NOFRAME))
+ {
+ /* FIXME: Handle WNDS_UPDATEDIRTY */
- if (Wnd->hrgnUpdate == NULL)
- Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- if (Flags & RDW_NOFRAME)
- Wnd->state &= ~WNDS_SENDNCPAINT;
- if (Flags & RDW_NOERASE)
- Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- }
+ if (Flags & RDW_NOINTERNALPAINT)
+ {
+ Wnd->state &= ~WNDS_INTERNALPAINT;
+ }
- if (Flags & RDW_INTERNALPAINT)
- {
- Wnd->state |= WNDS_INTERNALPAINT;
- }
+ if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
+ {
+ if (Flags & RDW_NOFRAME)
+ Wnd->state &= ~WNDS_SENDNCPAINT;
+ if (Flags & RDW_NOERASE)
+ Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- if (Flags & RDW_NOINTERNALPAINT)
- {
- Wnd->state &= ~WNDS_INTERNALPAINT;
+ if (Wnd->hrgnUpdate != NULL)
+ {
+ if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
+ hRgn, RGN_DIFF) == NULLREGION)
+ {
+ IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ GreDeleteObject(Wnd->hrgnUpdate);
+ Wnd->hrgnUpdate = NULL;
+ }
+ }
+
+ if (Wnd->hrgnUpdate == NULL)
+ Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+ }
}
/*
IntInvalidateWindows(Child, hRgnTemp, Flags);
GreDeleteObject(hRgnTemp);
}
-
}
}
* Fake post paint messages to window message queue if needed
*/
- HasPaintMessage = Wnd->hrgnUpdate != NULL ||
- Wnd->state & WNDS_INTERNALPAINT;
- HasNCPaintMessage = Wnd->state & WNDS_SENDNCPAINT;
-
- if (HasPaintMessage != HadPaintMessage)
+ if (HadPaintMessage != IntIsWindowDirty(Wnd))
{
if (HadPaintMessage)
MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
else
MsqIncPaintCountQueue(Wnd->head.pti->MessageQueue);
}
-
- if (HasNCPaintMessage != HadNCPaintMessage)
- {
- if (HadNCPaintMessage)
- MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
- else
- MsqIncPaintCountQueue(Wnd->head.pti->MessageQueue);
- }
TRACE("IntInvalidateWindows exit\n");
}
BOOL FASTCALL
IntIsWindowDirty(PWND Wnd)
{
- return (Wnd->style & WS_VISIBLE) &&
- ((Wnd->hrgnUpdate != NULL) ||
- (Wnd->state & WNDS_INTERNALPAINT) ||
- (Wnd->state & WNDS_SENDNCPAINT));
+ return ( Wnd->style & WS_VISIBLE &&
+ ( Wnd->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT ||
+ Wnd->state & WNDS_SENDNCPAINT ) );
}
-HWND FASTCALL
+PWND FASTCALL
IntFindWindowToRepaint(PWND Window, PTHREADINFO Thread)
{
- HWND hChild;
+ PWND hChild;
PWND TempWindow;
for (; Window != NULL; Window = Window->spwndNext)
IntWndBelongsToThread(TempWindow, Thread) &&
IntIsWindowDirty(TempWindow))
{
- return TempWindow->head.h;
+ return TempWindow;
}
}
}
- return Window->head.h;
+ return Window;
}
if (Window->spwndChild)
return hChild;
}
}
-
- return NULL;
+ return Window;
}
BOOL FASTCALL
MSG *Message,
BOOL Remove)
{
- if (!Thread->cPaintsReady)
- return FALSE;
+ PWND PaintWnd;
if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
(MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
return FALSE;
- Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetCurrentThreadWin32Thread());
+ if (Thread->TIF_flags & TIF_SYSTEMTHREAD )
+ {
+ ERR("WM_PAINT is in a System Thread!\n");
+ }
+
+ PaintWnd = IntFindWindowToRepaint(UserGetDesktopWindow(), Thread);
+
+ Message->hwnd = PaintWnd ? UserHMGetHandle(PaintWnd) : NULL;
if (Message->hwnd == NULL)
{
return FALSE;
}
- if (Window != NULL && Message->hwnd != Window->head.h)
+ if (Window != NULL && PaintWnd != Window)
return FALSE;
- Message->message = WM_PAINT;
+ if (PaintWnd->state & WNDS_INTERNALPAINT)
+ {
+ PaintWnd->state &= ~WNDS_INTERNALPAINT;
+ if (!PaintWnd->hrgnUpdate)
+ MsqDecPaintCountQueue(Thread->MessageQueue);
+ }
+ PaintWnd->state2 &= ~WNDS2_WMPAINTSENT;
+ PaintWnd->state &= ~WNDS_UPDATEDIRTY;
Message->wParam = Message->lParam = 0;
-
+ Message->message = WM_PAINT;
return TRUE;
}
co_UserHideCaret(Window);
+ Window->state2 |= WNDS2_STARTPAINT;
+ Window->state &= ~WNDS_PAINTNOTPROCESSED;
+
if (Window->state & WNDS_SENDNCPAINT)
{
HRGN hRgn;
+ Window->state &= ~WNDS_UPDATEDIRTY;
hRgn = IntGetNCUpdateRgn(Window, FALSE);
Window->state &= ~WNDS_SENDNCPAINT;
- MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
{
GreDeleteObject(hRgn);
}
}
+ else
+ {
+ Window->state &= ~WNDS_UPDATEDIRTY;
+ }
RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT));
PWND Child;
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{
+ if (Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) // Helped fixing test_redrawnow.
IntInvalidateWindows(Child, Window->hrgnUpdate, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
UserReleaseDC(Window, hdc, TRUE);
+ Window->state2 &= ~(WNDS2_WMPAINTSENT|WNDS2_STARTPAINT);
+
UserRefObjectCo(Window, &Ref);
co_UserShowCaret(Window);
UserDerefObjectCo(Window);
ASSERT_REFS_CO(Window);
+ Window->state &= ~WNDS_UPDATEDIRTY;
+
if (Window->hrgnUpdate == NULL)
{
RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
RETURN(FALSE);
}
+ Window->state &= ~WNDS_UPDATEDIRTY;
+
if (Window->hrgnUpdate == NULL)
{
Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
if (hwnd)
{
- Window = UserGetWindowObject(hwnd);
- // TODO: Add Desktop and MessageBox check via FNID's.
+ if (!(Window = UserGetWindowObject(hwnd)) || // FIXME:
+ Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
+ Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
+ {
+ goto Exit;
+ }
+
if ( Window )
{
/* Validate flags and check it as a mask for 0 or 1. */
EngSetLastError(ERROR_INVALID_PARAMETER);
}
}
-
+Exit:
UserLeave();
return Ret;
}