Fixes for painting.

svn path=/trunk/; revision=3398
This commit is contained in:
David Welch 2002-08-26 23:20:54 +00:00
parent 3f6d544a66
commit df75d0d97f
5 changed files with 343 additions and 19 deletions

View file

@ -107,6 +107,10 @@ MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue);
VOID
MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
PUSER_SENT_MESSAGE_NOTIFY NotifyMessage);
VOID
MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue);
VOID
MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue);
LRESULT STDCALL
W32kSendMessage(HWND hWnd,
UINT Msg,

View file

@ -107,6 +107,7 @@ BOOL
W32kIsWindowVisible(HWND Wnd);
BOOL
W32kIsChildWindow(HWND Parent, HWND Child);
HWND W32kGetDesktopWindow();
#endif /* __WIN32K_WINDOW_H */

View file

@ -1,4 +1,4 @@
/* $Id: message.c,v 1.8 2002/07/17 21:04:57 dwelch Exp $
/* $Id: message.c,v 1.9 2002/08/26 23:20:54 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -181,9 +181,35 @@ NtUserGetMessage(LPMSG lpMsg,
/* Check for paint messages. */
if (ThreadQueue->PaintPosted)
{
PWINDOW_OBJECT WindowObject;
lpMsg->hwnd = PaintingFindWinToRepaint(hWnd, PsGetWin32Thread());
lpMsg->message = WM_PAINT;
lpMsg->wParam = lpMsg->lParam = 0;
WindowObject = W32kGetWindowObject(lpMsg->hwnd);
if (WindowObject != NULL)
{
if (WindowObject->Style & WS_MINIMIZE &&
(HICON)NtUserGetClassLong(lpMsg->hwnd, GCL_HICON) != NULL)
{
lpMsg->message = WM_PAINTICON;
lpMsg->wParam = 1;
}
if (lpMsg->hwnd == NULL || lpMsg->hwnd == hWnd ||
W32kIsChildWindow(hWnd, lpMsg->hwnd))
{
if (WindowObject->Flags & WINDOWOBJECT_NEED_INTERNALPAINT &&
WindowObject->UpdateRegion == NULL)
{
WindowObject->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
MsqDecPaintCountQueue(WindowObject->MessageQueue);
}
}
W32kReleaseWindowObject(WindowObject);
}
return(TRUE);
}

View file

@ -1,4 +1,4 @@
/* $Id: painting.c,v 1.2 2002/07/18 21:59:18 ei Exp $
/* $Id: painting.c,v 1.3 2002/08/26 23:20:54 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -123,11 +123,292 @@ PaintDoPaint(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags, ULONG ExFlags)
return(hRgn);
}
VOID STATIC
PaintUpdateInternalPaint(PWINDOW_OBJECT Window, ULONG Flags)
{
if (Flags & RDW_INTERNALPAINT)
{
if (Window->UpdateRegion == NULL &&
!(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT))
{
MsqIncPaintCountQueue(Window->MessageQueue);
}
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
}
else if (Flags & RDW_NOINTERNALPAINT)
{
if (Window->UpdateRegion == NULL &&
(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT))
{
MsqDecPaintCountQueue(Window->MessageQueue);
}
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
}
}
VOID STATIC
PaintValidateParent(PWINDOW_OBJECT Child)
{
HWND DesktopHandle = W32kGetDesktopWindow();
PWINDOW_OBJECT Parent = Child->Parent;
PWINDOW_OBJECT Desktop = W32kGetWindowObject(DesktopHandle);
HRGN hRgn;
if (Child->UpdateRegion == (HANDLE)1)
{
RECT Rect;
Rect.left = Rect.top = 0;
Rect.right = Child->WindowRect.right - Child->WindowRect.left;
Rect.bottom = Child->WindowRect.bottom - Child->WindowRect.top;
hRgn = W32kCreateRectRgnIndirect(&Rect);
}
else
{
hRgn = Child->UpdateRegion;
}
while (Parent != NULL && Parent != Desktop)
{
if (!(Parent->Style & WS_CLIPCHILDREN))
{
if (Parent->UpdateRegion != (HANDLE)0)
{
POINT Offset;
if (Parent->UpdateRegion == (HANDLE)1)
{
RECT Rect1;
Rect1.left = Rect1.top = 0;
Rect1.right = Parent->WindowRect.right -
Parent->WindowRect.left;
Rect1.bottom = Parent->WindowRect.bottom -
Parent->WindowRect.top;
Parent->UpdateRegion = W32kCreateRectRgnIndirect(&Rect1);
}
Offset.x = Child->WindowRect.left - Parent->WindowRect.left;
Offset.y = Child->WindowRect.top - Parent->WindowRect.top;
W32kOffsetRgn(hRgn, Offset.x, Offset.y);
W32kCombineRgn(Parent->UpdateRegion, Parent->UpdateRegion, hRgn,
RGN_DIFF);
W32kOffsetRgn(hRgn, -Offset.x, -Offset.y);
}
}
Parent = Parent->Parent;
}
if (hRgn != Child->UpdateRegion)
{
W32kDeleteObject(Child->UpdateRegion);
}
W32kReleaseWindowObject(Desktop);
}
VOID STATIC
PaintUpdateRgns(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags,
BOOL First)
{
BOOL HadOne = Window->UpdateRegion != NULL && hRgn;
BOOL HasChildren = !IsListEmpty(&Window->ChildrenListHead) &&
!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN));
RECT Rect;
Rect.left = Rect.top = 0;
Rect.right = Window->WindowRect.right - Window->WindowRect.left;
Rect.bottom = Window->WindowRect.bottom - Window->WindowRect.top;
if (Flags & RDW_INVALIDATE)
{
if (hRgn > (HANDLE)1)
{
if (Window->UpdateRegion > (HANDLE)1)
{
W32kCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
hRgn, RGN_OR);
Window->UpdateRegion =
REGION_CropRgn(Window->UpdateRegion,
Window->UpdateRegion, &Rect, NULL);
if (!HadOne)
{
W32kGetRgnBox(Window->UpdateRegion, &Rect);
if (W32kIsEmptyRect(&Rect))
{
W32kDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
PaintUpdateInternalPaint(Window, Flags);
return;
}
}
}
else if (Window->UpdateRegion == 0)
{
Window->UpdateRegion =
REGION_CropRgn(Window->UpdateRegion, hRgn, &Rect, NULL);
if (!HadOne)
{
W32kGetRgnBox(Window->UpdateRegion, &Rect);
if (W32kIsEmptyRect(&Rect))
{
W32kDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
PaintUpdateInternalPaint(Window, Flags);
return;
}
}
}
}
else if (hRgn == (HANDLE)1)
{
if (Window->UpdateRegion > (HANDLE)1)
{
W32kDeleteObject(Window->UpdateRegion);
}
Window->UpdateRegion = (HANDLE)1;
}
else
{
hRgn = Window->UpdateRegion;
}
if (!HadOne && !(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT))
{
MsqIncPaintCountQueue(Window->MessageQueue);
}
if (Flags & RDW_FRAME)
{
Window->Flags |= WINDOWOBJECT_NEED_NCPAINT;
}
if (Flags & RDW_ERASE)
{
Window->Flags |= WINDOWOBJECT_NEED_ERASEBACKGRD;
}
Flags |= RDW_FRAME;
}
else if (Flags & RDW_VALIDATE)
{
if (Window->UpdateRegion != NULL)
{
if (hRgn > (HANDLE)1)
{
if (Window->UpdateRegion == (HANDLE)1)
{
Window->UpdateRegion =
W32kCreateRectRgnIndirect(&Rect);
}
if (W32kCombineRgn(Window->UpdateRegion,
Window->UpdateRegion, hRgn,
RGN_DIFF) == NULLREGION)
{
if (Window->UpdateRegion > (HANDLE)1)
{
W32kDeleteObject(Window->UpdateRegion);
}
Window->UpdateRegion = NULL;
}
}
else
{
if (Window->UpdateRegion > (HANDLE)1)
{
W32kDeleteObject(Window->UpdateRegion);
}
Window->UpdateRegion = NULL;
}
if (Window->UpdateRegion == NULL)
{
Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD;
if (!(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT))
{
MsqIncPaintCountQueue(Window->MessageQueue);
}
}
}
if (Flags & RDW_NOFRAME)
{
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
}
if (Flags & RDW_NOERASE)
{
Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD;
}
}
if (First && Window->UpdateRegion != NULL && (Flags & RDW_UPDATENOW))
{
PaintValidateParent(Window);
}
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE))
{
if (hRgn > (HANDLE)1 && HasChildren)
{
POINT Total = {0, 0};
POINT PrevOrign = {0, 0};
POINT Client;
PWINDOW_OBJECT Child;
PLIST_ENTRY ChildListEntry;
Client.x = Window->ClientRect.left - Window->WindowRect.left;
Client.y = Window->ClientRect.top - Window->WindowRect.top;
ChildListEntry = Window->ChildrenListHead.Flink;
while (ChildListEntry != &Window->ChildrenListHead)
{
Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT,
SiblingListEntry);
if (Child->Style & WS_VISIBLE)
{
POINT Offset;
Rect.left = Window->WindowRect.left + Client.x;
Rect.right = Window->WindowRect.right + Client.x;
Rect.top = Window->WindowRect.top + Client.y;
Rect.bottom = Window->WindowRect.bottom + Client.y;
Offset.x = Rect.left - PrevOrign.x;
Offset.y = Rect.top - PrevOrign.y;
W32kOffsetRect(&Rect, -Total.x, -Total.y);
if (W32kRectInRegion(hRgn, &Rect))
{
W32kOffsetRgn(hRgn, -Total.x, -Total.y);
PaintUpdateRgns(Child, hRgn, Flags, FALSE);
PrevOrign.x = Rect.left + Total.x;
PrevOrign.y = Rect.right + Total.y;
Total.x += Offset.x;
Total.y += Offset.y;
}
}
}
W32kOffsetRgn(hRgn, Total.x, Total.y);
HasChildren = FALSE;
}
}
if (HasChildren)
{
PWINDOW_OBJECT Child;
PLIST_ENTRY ChildListEntry;
ChildListEntry = Window->ChildrenListHead.Flink;
while (ChildListEntry != &Window->ChildrenListHead)
{
Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT,
SiblingListEntry);
if (Child->Style & WS_VISIBLE)
{
PaintUpdateRgns(Child, hRgn, Flags, FALSE);
}
}
}
PaintUpdateInternalPaint(Window, Flags);
}
BOOL
@ -214,10 +495,14 @@ PaintRedrawWindow(HWND hWnd, const RECT* UpdateRect, HRGN UpdateRgn,
}
}
}
else if (Flags & RDW_VALIDATE)
{
/* FIXME: Implement this. */
}
PaintUpdateRgns(Window, hRgn, Flags, TRUE);
hRgn = PaintDoPaint(Window, hRgn == 1 ? 0 : hRgn, Flags, ExFlags);
hRgn = PaintDoPaint(Window, hRgn == (HANDLE)1 ? 0 : hRgn, Flags, ExFlags);
if (hRgn != (HANDLE)1 && hRgn != UpdateRgn)
{
@ -271,30 +556,30 @@ PaintingFindWinToRepaint(HWND hWnd, PW32THREAD Thread)
ThreadListEntry);
if (Window->Style & WS_VISIBLE)
{
hFoundWnd = PaintingFindWinToRepaint(hWnd, Thread);
hFoundWnd =
PaintingFindWinToRepaint(Window->Self, Thread);
if (hFoundWnd != NULL)
{
break;
ExReleaseFastMutex(&Thread->WindowListLock);
return(hFoundWnd);
}
}
current_entry = current_entry->Flink;
}
ExReleaseFastMutex(&Thread->WindowListLock);
return(hFoundWnd);
return(NULL);
}
Status =
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
hWnd,
otWindow,
(PVOID*)&BaseWindow);
if (!NT_SUCCESS(Status))
BaseWindow = W32kGetWindowObject(hWnd);
if (BaseWindow == NULL)
{
return(NULL);
}
if (BaseWindow->Style & WS_VISIBLE && BaseWindow->UpdateRegion != NULL)
if (BaseWindow->UpdateRegion != NULL ||
BaseWindow->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
return(BaseWindow->Self);
W32kReleaseWindowObject(BaseWindow);
return(hWnd);
}
ExAcquireFastMutex(&BaseWindow->ChildrenListLock);
@ -305,7 +590,7 @@ PaintingFindWinToRepaint(HWND hWnd, PW32THREAD Thread)
ThreadListEntry);
if (Window->Style & WS_VISIBLE)
{
hFoundWnd = PaintingFindWinToRepaint(hWnd, Thread);
hFoundWnd = PaintingFindWinToRepaint(Window->Self, Thread);
if (hFoundWnd != NULL)
{
break;
@ -314,6 +599,7 @@ PaintingFindWinToRepaint(HWND hWnd, PW32THREAD Thread)
current_entry = current_entry->Flink;
}
ExReleaseFastMutex(&BaseWindow->ChildrenListLock);
W32kReleaseWindowObject(BaseWindow);
return(hFoundWnd);
}
@ -480,10 +766,13 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs)
/* FIXME: Check the window is still valid. */
/* FIXME: Decrement the paint count if the update region is non-zero. */
UpdateRegion = Window->UpdateRegion;
Window->UpdateRegion = 0;
if (UpdateRegion != NULL || Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
MsqDecPaintCountQueue(&Window->MessageQueue);
}
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
/* FIXME: Hide claret. */

View file

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.10 2002/08/24 11:09:17 jfilby Exp $
/* $Id: window.c,v 1.11 2002/08/26 23:20:54 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -247,6 +247,7 @@ W32kCreateDesktopWindow(PWINSTATION_OBJECT WindowStation,
WindowObject->WindowRect.right = Width;
WindowObject->WindowRect.bottom = Height;
WindowObject->ClientRect = WindowObject->WindowRect;
InitializeListHead(&WindowObject->ChildrenListHead);
WindowName = ExAllocatePool(NonPagedPool, sizeof(L"DESKTOP"));
wcscpy(WindowName, L"DESKTOP");
@ -358,6 +359,9 @@ NtUserCreateWindowEx(DWORD dwExStyle,
WindowObject->Self = Handle;
WindowObject->MessageQueue = PsGetWin32Thread()->MessageQueue;
WindowObject->Parent = ParentWindow;
InsertHeadList(&ParentWindow->ChildrenListHead,
&WindowObject->SiblingListEntry);
InitializeListHead(&WindowObject->ChildrenListHead);
RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer);
RtlFreeUnicodeString(&WindowName);
@ -389,7 +393,7 @@ NtUserCreateWindowEx(DWORD dwExStyle,
/* Insert the window into the process's window list. */
ExAcquireFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock);
InsertTailList (&PsGetWin32Thread()->WindowListHead,
&WindowObject->ListEntry);
&WindowObject->ThreadListEntry);
ExReleaseFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock);
/*