Author: jimtabor
Date: Thu Jul 5 22:04:47 2012
New Revision: 56839
URL:
http://svn.reactos.org/svn/reactos?rev=56839&view=rev
Log:
[Win32SS]
- Paint updates and signaling flags.
- WIP: Implement WM_SYNCPAINT support, for synchronize painting to the top-level windows
of other threads.
- Tested with wine tests and passes,
http://www.winehq.org/pipermail/wine-patches/2012-June/114714.html
http://www.winehq.org/pipermail/wine-patches/2012-June/114715.html
Modified:
trunk/reactos/win32ss/user/ntuser/painting.c
trunk/reactos/win32ss/user/user32/windows/defwnd.c
Modified: trunk/reactos/win32ss/user/ntuser/painting.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/painti…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/painting.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/painting.c [iso-8859-1] Thu Jul 5 22:04:47 2012
@@ -58,8 +58,18 @@
BOOL FASTCALL
IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
{
- PWND ParentWnd = Child->spwndParent;
-
+ PWND ParentWnd = Child;
+
+ if (ParentWnd->style & WS_CHILD)
+ {
+ do
+ ParentWnd = ParentWnd->spwndParent;
+ while (ParentWnd->style & WS_CHILD);
+ }
+// Hax out for drawing issues.
+// if (!(ParentWnd->state & WNDS_SYNCPAINTPENDING)) Recurse = FALSE;
+
+ ParentWnd = Child->spwndParent;
while (ParentWnd)
{
if (ParentWnd->style & WS_CLIPCHILDREN)
@@ -79,6 +89,81 @@
}
return TRUE;
+}
+
+/*
+ Synchronize painting to the top-level windows of other threads.
+*/
+VOID FASTCALL
+IntSendSyncPaint(PWND Wnd, ULONG Flags)
+{
+ PTHREADINFO ptiCur;
+ PUSER_MESSAGE_QUEUE MessageQueue;
+ PUSER_SENT_MESSAGE Message;
+ PLIST_ENTRY Entry;
+ BOOL bSend = TRUE;
+
+ MessageQueue = Wnd->head.pti->MessageQueue;
+ ptiCur = PsGetCurrentThreadWin32Thread();
+ /*
+ Not the current thread, Wnd is in send Nonclient paint also in send erase
background and it is visiable.
+ */
+ if ( Wnd->head.pti != ptiCur &&
+ Wnd->state & WNDS_SENDNCPAINT &&
+ Wnd->state & WNDS_SENDERASEBACKGROUND &&
+ Wnd->style & WS_VISIBLE)
+ {
+ // For testing, if you see this, break out the Champagne and have a party!
+ ERR("SendSyncPaint Wnd in State!\n");
+ if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+ {
+ // Scan sent queue messages to see if we received sync paint messages.
+ Entry = MessageQueue->SentMessagesListHead.Flink;
+ Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ do
+ {
+ ERR("LOOP it\n");
+ if (Message->Msg.message == WM_SYNCPAINT &&
+ Message->Msg.hwnd == UserHMGetHandle(Wnd))
+ { // Already received so exit out.
+ ERR("SendSyncPaint Found one in the Sent Msg Queue!\n");
+ bSend = FALSE;
+ break;
+ }
+ Entry = Message->ListEntry.Flink;
+ Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ }
+ while (Entry != &MessageQueue->SentMessagesListHead);
+ }
+ if (bSend)
+ {
+ ERR("Sending WM_SYNCPAINT\n");
+ // This message has no parameters. But it does! Pass Flags along.
+ co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SYNCPAINT, Flags, 0);
+ Wnd->state |= WNDS_SYNCPAINTPENDING;
+ }
+ }
+
+ // Send to all the children if this is the desktop window.
+ if ( Wnd == UserGetDesktopWindow() )
+ {
+ if ( Flags & RDW_ALLCHILDREN ||
+ ( !(Flags & RDW_NOCHILDREN) && Wnd->style &
WS_CLIPCHILDREN))
+ {
+ PWND spwndChild = Wnd->spwndChild;
+ while(spwndChild)
+ {
+ if ( spwndChild->style & WS_CHILD &&
+ spwndChild->head.pti != ptiCur)
+ {
+ spwndChild = spwndChild->spwndNext;
+ continue;
+ }
+ IntSendSyncPaint( spwndChild, Flags );
+ spwndChild = spwndChild->spwndNext;
+ }
+ }
+ }
}
/**
@@ -166,6 +251,7 @@
{
GreDeleteObject(hRgnWindow);
GreDeleteObject(hRgnNonClient);
+ Window->state &= ~WNDS_UPDATEDIRTY;
return NULL;
}
@@ -181,6 +267,7 @@
{
IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Window->hrgnUpdate);
+ Window->state &= ~WNDS_UPDATEDIRTY;
Window->hrgnUpdate = NULL;
if (!(Window->state & WNDS_INTERNALPAINT))
MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
@@ -210,6 +297,8 @@
HWND hWnd = Wnd->head.h;
HRGN TempRegion;
+ Wnd->state &= ~WNDS_PAINTNOTPROCESSED;
+
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{
if (Wnd->hrgnUpdate)
@@ -220,20 +309,26 @@
if (Flags & RDW_UPDATENOW)
{
- if (Wnd->hrgnUpdate != NULL ||
- Wnd->state & WNDS_INTERNALPAINT)
+ if ((Wnd->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT))
{
Wnd->state2 |= WNDS2_WMPAINTSENT;
co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
}
}
- else
+ else if (Wnd->head.pti == PsGetCurrentThreadWin32Thread())
{
if (Wnd->state & WNDS_SENDNCPAINT)
{
TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
Wnd->state &= ~WNDS_SENDNCPAINT;
- co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
+ if ( Wnd == GetW32ThreadInfo()->MessageQueue->spwndActive &&
+ !(Wnd->state & WNDS_ACTIVEFRAME))
+ {
+ Wnd->state |= WNDS_ACTIVEFRAME;
+ Wnd->state &= ~WNDS_NONCPAINT;
+ }
+ if (TempRegion) co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
}
if (Wnd->state & WNDS_SENDERASEBACKGROUND)
@@ -254,6 +349,10 @@
}
}
}
+ }
+ else
+ {
+ Wnd->state &=
~(WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
}
/*
@@ -306,6 +405,8 @@
TRACE("IntInvalidateWindows start\n");
+ Wnd->state |= WNDS_PAINTNOTPROCESSED;
+
/*
* If the nonclient is not to be redrawn, clip the region to the client
* rect
@@ -362,10 +463,14 @@
if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
{
+ Wnd->state &= ~WNDS_NONCPAINT;
+
/* If not the same thread set it dirty. */
if (Wnd->head.pti != PsGetCurrentThreadWin32Thread())
{
Wnd->state |= WNDS_UPDATEDIRTY;
+ if (Wnd->state2 & WNDS2_WMPAINTSENT)
+ Wnd->state2 |= WNDS2_ENDPAINTINVALIDATE;
}
if (Flags & RDW_FRAME)
@@ -572,6 +677,7 @@
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{
+ if (Flags & RDW_ERASENOW) IntSendSyncPaint(Window, Flags);
co_IntPaintWindows(Window, Flags, FALSE);
}
@@ -853,7 +959,7 @@
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
{
- /* NOTE: The region can already by deleted! */
+ /* NOTE: The region can already be deleted! */
GreDeleteObject(hRgn);
}
}
@@ -928,7 +1034,7 @@
CLEANUP:
if (Window) UserDerefObjectCo(Window);
- TRACE("Leave NtUserBeginPaint, ret=%i\n",_ret_);
+ TRACE("Leave NtUserBeginPaint, ret=%p\n",_ret_);
UserLeave();
END_CLEANUP;
@@ -1869,11 +1975,13 @@
return Ret;
}
+BOOL FASTCALL IntPaintDesktop(HDC hDC);
+
INT
FASTCALL
UserRealizePalette(HDC hdc)
{
- HWND hWnd;
+ HWND hWnd, hWndDesktop;
DWORD Ret;
Ret = IntGdiRealizePalette(hdc);
@@ -1882,6 +1990,15 @@
hWnd = IntWindowFromDC(hdc);
if (hWnd) // Send broadcast if dc is associated with a window.
{ // FYI: Thread locked in CallOneParam.
+ hWndDesktop = IntGetDesktopWindow();
+ if ( hWndDesktop != hWnd )
+ {
+ PWND pWnd = UserGetWindowObject(hWndDesktop);
+ ERR("RealizePalette Desktop.");
+ hdc = UserGetWindowDC(pWnd);
+ IntPaintDesktop(hdc);
+ UserReleaseDC(pWnd,hdc,FALSE);
+ }
UserSendNotifyMessage((HWND)HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)hWnd,
0);
}
}
Modified: trunk/reactos/win32ss/user/user32/windows/defwnd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/window…
==============================================================================
--- trunk/reactos/win32ss/user/user32/windows/defwnd.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/user32/windows/defwnd.c [iso-8859-1] Thu Jul 5 22:04:47
2012
@@ -1209,13 +1209,20 @@
case WM_PAINT:
{
PAINTSTRUCT Ps;
+
+ /* If already in Paint and Client area is not empty just return. */
+ if (pWnd->state2 & WNDS2_STARTPAINT &&
!IsRectEmpty(&pWnd->rcClient))
+ {
+ ERR("In Paint and Client area is not empty!\n");
+ return 0;
+ }
+
HDC hDC = BeginPaint(hWnd, &Ps);
if (hDC)
{
HICON hIcon;
- if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
- (hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON)) != NULL)
+ if (IsIconic(hWnd) && ((hIcon = (HICON)GetClassLongPtrW( hWnd,
GCLP_HICON))))
{
RECT ClientRect;
INT x, y;