mirror of
https://github.com/reactos/reactos.git
synced 2025-06-11 04:47:22 +00:00
[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 svn path=/trunk/; revision=56839
This commit is contained in:
parent
a117d3a0ca
commit
1e0937de1c
2 changed files with 134 additions and 10 deletions
|
@ -58,8 +58,18 @@ IntIntersectWithParents(PWND Child, RECTL *WindowRect)
|
||||||
BOOL FASTCALL
|
BOOL FASTCALL
|
||||||
IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
|
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)
|
while (ParentWnd)
|
||||||
{
|
{
|
||||||
if (ParentWnd->style & WS_CLIPCHILDREN)
|
if (ParentWnd->style & WS_CLIPCHILDREN)
|
||||||
|
@ -81,6 +91,81 @@ IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
|
||||||
return TRUE;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name IntCalcWindowRgn
|
* @name IntCalcWindowRgn
|
||||||
*
|
*
|
||||||
|
@ -166,6 +251,7 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
|
||||||
{
|
{
|
||||||
GreDeleteObject(hRgnWindow);
|
GreDeleteObject(hRgnWindow);
|
||||||
GreDeleteObject(hRgnNonClient);
|
GreDeleteObject(hRgnNonClient);
|
||||||
|
Window->state &= ~WNDS_UPDATEDIRTY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +267,7 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
|
||||||
{
|
{
|
||||||
IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
|
IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
|
||||||
GreDeleteObject(Window->hrgnUpdate);
|
GreDeleteObject(Window->hrgnUpdate);
|
||||||
|
Window->state &= ~WNDS_UPDATEDIRTY;
|
||||||
Window->hrgnUpdate = NULL;
|
Window->hrgnUpdate = NULL;
|
||||||
if (!(Window->state & WNDS_INTERNALPAINT))
|
if (!(Window->state & WNDS_INTERNALPAINT))
|
||||||
MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
|
MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
|
||||||
|
@ -210,6 +297,8 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
|
||||||
HWND hWnd = Wnd->head.h;
|
HWND hWnd = Wnd->head.h;
|
||||||
HRGN TempRegion;
|
HRGN TempRegion;
|
||||||
|
|
||||||
|
Wnd->state &= ~WNDS_PAINTNOTPROCESSED;
|
||||||
|
|
||||||
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
|
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
|
||||||
{
|
{
|
||||||
if (Wnd->hrgnUpdate)
|
if (Wnd->hrgnUpdate)
|
||||||
|
@ -220,20 +309,26 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
|
||||||
|
|
||||||
if (Flags & RDW_UPDATENOW)
|
if (Flags & RDW_UPDATENOW)
|
||||||
{
|
{
|
||||||
if (Wnd->hrgnUpdate != NULL ||
|
if ((Wnd->hrgnUpdate != NULL ||
|
||||||
Wnd->state & WNDS_INTERNALPAINT)
|
Wnd->state & WNDS_INTERNALPAINT))
|
||||||
{
|
{
|
||||||
Wnd->state2 |= WNDS2_WMPAINTSENT;
|
Wnd->state2 |= WNDS2_WMPAINTSENT;
|
||||||
co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
|
co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (Wnd->head.pti == PsGetCurrentThreadWin32Thread())
|
||||||
{
|
{
|
||||||
if (Wnd->state & WNDS_SENDNCPAINT)
|
if (Wnd->state & WNDS_SENDNCPAINT)
|
||||||
{
|
{
|
||||||
TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
|
TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
|
||||||
Wnd->state &= ~WNDS_SENDNCPAINT;
|
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)
|
if (Wnd->state & WNDS_SENDERASEBACKGROUND)
|
||||||
|
@ -255,6 +350,10 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Wnd->state &= ~(WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the window is still valid at this point
|
* Check that the window is still valid at this point
|
||||||
|
@ -306,6 +405,8 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
|
||||||
|
|
||||||
TRACE("IntInvalidateWindows start\n");
|
TRACE("IntInvalidateWindows start\n");
|
||||||
|
|
||||||
|
Wnd->state |= WNDS_PAINTNOTPROCESSED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the nonclient is not to be redrawn, clip the region to the client
|
* If the nonclient is not to be redrawn, clip the region to the client
|
||||||
* rect
|
* rect
|
||||||
|
@ -362,10 +463,14 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
|
||||||
|
|
||||||
if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
|
if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
|
||||||
{
|
{
|
||||||
|
Wnd->state &= ~WNDS_NONCPAINT;
|
||||||
|
|
||||||
/* If not the same thread set it dirty. */
|
/* If not the same thread set it dirty. */
|
||||||
if (Wnd->head.pti != PsGetCurrentThreadWin32Thread())
|
if (Wnd->head.pti != PsGetCurrentThreadWin32Thread())
|
||||||
{
|
{
|
||||||
Wnd->state |= WNDS_UPDATEDIRTY;
|
Wnd->state |= WNDS_UPDATEDIRTY;
|
||||||
|
if (Wnd->state2 & WNDS2_WMPAINTSENT)
|
||||||
|
Wnd->state2 |= WNDS2_ENDPAINTINVALIDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags & RDW_FRAME)
|
if (Flags & RDW_FRAME)
|
||||||
|
@ -572,6 +677,7 @@ co_UserRedrawWindow(
|
||||||
|
|
||||||
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
|
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
|
||||||
{
|
{
|
||||||
|
if (Flags & RDW_ERASENOW) IntSendSyncPaint(Window, Flags);
|
||||||
co_IntPaintWindows(Window, Flags, FALSE);
|
co_IntPaintWindows(Window, Flags, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,7 +959,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
|
||||||
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
|
co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
|
||||||
if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
|
if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
|
||||||
{
|
{
|
||||||
/* NOTE: The region can already by deleted! */
|
/* NOTE: The region can already be deleted! */
|
||||||
GreDeleteObject(hRgn);
|
GreDeleteObject(hRgn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,7 +1034,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
|
||||||
CLEANUP:
|
CLEANUP:
|
||||||
if (Window) UserDerefObjectCo(Window);
|
if (Window) UserDerefObjectCo(Window);
|
||||||
|
|
||||||
TRACE("Leave NtUserBeginPaint, ret=%i\n",_ret_);
|
TRACE("Leave NtUserBeginPaint, ret=%p\n",_ret_);
|
||||||
UserLeave();
|
UserLeave();
|
||||||
END_CLEANUP;
|
END_CLEANUP;
|
||||||
|
|
||||||
|
@ -1869,11 +1975,13 @@ cleanup:
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL FASTCALL IntPaintDesktop(HDC hDC);
|
||||||
|
|
||||||
INT
|
INT
|
||||||
FASTCALL
|
FASTCALL
|
||||||
UserRealizePalette(HDC hdc)
|
UserRealizePalette(HDC hdc)
|
||||||
{
|
{
|
||||||
HWND hWnd;
|
HWND hWnd, hWndDesktop;
|
||||||
DWORD Ret;
|
DWORD Ret;
|
||||||
|
|
||||||
Ret = IntGdiRealizePalette(hdc);
|
Ret = IntGdiRealizePalette(hdc);
|
||||||
|
@ -1882,6 +1990,15 @@ UserRealizePalette(HDC hdc)
|
||||||
hWnd = IntWindowFromDC(hdc);
|
hWnd = IntWindowFromDC(hdc);
|
||||||
if (hWnd) // Send broadcast if dc is associated with a window.
|
if (hWnd) // Send broadcast if dc is associated with a window.
|
||||||
{ // FYI: Thread locked in CallOneParam.
|
{ // 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);
|
UserSendNotifyMessage((HWND)HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)hWnd, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1209,13 +1209,20 @@ User32DefWindowProc(HWND hWnd,
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
{
|
{
|
||||||
PAINTSTRUCT Ps;
|
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);
|
HDC hDC = BeginPaint(hWnd, &Ps);
|
||||||
if (hDC)
|
if (hDC)
|
||||||
{
|
{
|
||||||
HICON hIcon;
|
HICON hIcon;
|
||||||
|
|
||||||
if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
|
if (IsIconic(hWnd) && ((hIcon = (HICON)GetClassLongPtrW( hWnd, GCLP_HICON))))
|
||||||
(hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON)) != NULL)
|
|
||||||
{
|
{
|
||||||
RECT ClientRect;
|
RECT ClientRect;
|
||||||
INT x, y;
|
INT x, y;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue