* 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.36 2003/11/20 21:21:29 navaraf Exp $
+ * $Id: painting.c,v 1.37 2003/11/21 17:01:16 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* PRIVATE FUNCTIONS **********************************************************/
+VOID FASTCALL
+IntValidateParent(PWINDOW_OBJECT Child)
+{
+ HWND Parent;
+ PWINDOW_OBJECT ParentWindow;
+
+ Parent = NtUserGetAncestor(Child->Self, GA_PARENT);
+ while (Parent && Parent != IntGetDesktopWindow())
+ {
+ ParentWindow = IntGetWindowObject(Parent);
+ if (ParentWindow && !(ParentWindow->Style & WS_CLIPCHILDREN))
+ {
+ if (ParentWindow->UpdateRegion != 0)
+ {
+ INT OffsetX, OffsetY;
+
+ /*
+ * 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(Child->UpdateRegion, OffsetX, OffsetY );
+ NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion,
+ Child->UpdateRegion, RGN_DIFF);
+ /* FIXME: If the resulting region is empty, remove fake posted paint message */
+ NtGdiOffsetRgn(Child->UpdateRegion, -OffsetX, -OffsetY);
+ }
+ }
+ IntReleaseWindowObject(ParentWindow);
+ Parent = NtUserGetAncestor(Parent, GA_PARENT);
+ }
+}
+
/*
* IntGetNCUpdateRegion
*
* Remarks
* This function also marks the nonclient update region of window
* as valid, clears the WINDOWOBJECT_NEED_NCPAINT flag and removes
- * the fake paint message from message queue.
+ * the fake paint message from message queue if the Remove is set
+ * to TRUE.
*/
HRGN FASTCALL
-IntGetNCUpdateRegion(PWINDOW_OBJECT Window)
+IntGetNCUpdateRegion(PWINDOW_OBJECT Window, BOOL Remove)
{
HRGN WindowRgn;
HRGN NonclientRgn;
- Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
- MsqDecPaintCountQueue(Window->MessageQueue);
WindowRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
NtGdiOffsetRgn(WindowRgn,
-Window->WindowRect.left,
NtGdiDeleteObject(NonclientRgn);
NonclientRgn = NULL;
}
- if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
- WindowRgn, RGN_AND) == NULLREGION)
+ if (Remove)
{
- NtGdiDeleteObject(Window->UpdateRegion);
- Window->UpdateRegion = NULL;
+ if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
+ WindowRgn, RGN_AND) == NULLREGION)
+ {
+ NtGdiDeleteObject(Window->UpdateRegion);
+ Window->UpdateRegion = NULL;
+ }
+ Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
+ MsqDecPaintCountQueue(Window->MessageQueue);
}
return NonclientRgn;
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
- NtUserSendMessage(hWnd, WM_NCPAINT, (WPARAM)IntGetNCUpdateRegion(Window), 0);
+ NtUserSendMessage(hWnd, WM_NCPAINT, (WPARAM)IntGetNCUpdateRegion(Window, TRUE), 0);
}
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
{
INT RgnType;
+ BOOL HadPaintMessage, HadNCPaintMessage;
+ BOOL HasPaintMessage, HasNCPaintMessage;
- if (!(Window->Style & WS_VISIBLE))
- {
- return;
- }
-
/*
* Clip the given region with window rectangle (or region)
*/
-Window->WindowRect.left,
-Window->WindowRect.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
+ NtGdiDeleteObject(hRgnWindow);
}
#ifdef TODO
else
}
#endif
- if (RgnType == NULLREGION)
- {
- return;
- }
-
/*
- * Remove fake posted paint messages from window message queue
+ * Save current state of pending updates
*/
-#ifndef DESKTOP_IN_CSRSS
- if (!IntIsDesktopWindow(Window))
- {
-#endif
- if (Window->UpdateRegion != NULL ||
- Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
- {
- MsqDecPaintCountQueue(Window->MessageQueue);
- }
-
- if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
- {
- MsqDecPaintCountQueue(Window->MessageQueue);
- }
-#ifndef DESKTOP_IN_CSRSS
- }
-#endif
+ HadPaintMessage = Window->UpdateRegion != NULL ||
+ Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
+ HadNCPaintMessage = Window->Flags & WINDOWOBJECT_NEED_NCPAINT;
/*
* Update the region and flags
*/
- if (Flags & RDW_INVALIDATE)
+ if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
{
if (Window->UpdateRegion == NULL)
{
Flags |= RDW_FRAME;
}
- if (Flags & RDW_VALIDATE)
+ if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
{
if (Window->UpdateRegion != NULL)
{
}
}
+ if (Window->UpdateRegion == NULL)
+ Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBKGND;
if (Flags & RDW_NOFRAME)
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
if (Flags & RDW_NOERASE)
}
/*
- * Fake post paint messages to window message queue
+ * Fake post paint messages to window message queue if needed
*/
#ifndef DESKTOP_IN_CSRSS
- if (!IntIsDesktopWindow(Window))
- {
+ if (Window->MessageQueue)
#endif
- if (Window->UpdateRegion != NULL ||
- Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
+ {
+ HasPaintMessage = Window->UpdateRegion != NULL ||
+ Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
+ HasNCPaintMessage = Window->Flags & WINDOWOBJECT_NEED_NCPAINT;
+
+ if (HasPaintMessage != HadPaintMessage)
{
- MsqIncPaintCountQueue(Window->MessageQueue);
+ if (HadPaintMessage)
+ MsqDecPaintCountQueue(Window->MessageQueue);
+ else
+ MsqIncPaintCountQueue(Window->MessageQueue);
}
- if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
+ if (HasNCPaintMessage != HadNCPaintMessage)
{
- MsqIncPaintCountQueue(Window->MessageQueue);
+ if (HadNCPaintMessage)
+ MsqDecPaintCountQueue(Window->MessageQueue);
+ else
+ MsqIncPaintCountQueue(Window->MessageQueue);
}
#ifndef DESKTOP_IN_CSRSS
}
{
for (phWnd = List; *phWnd; ++phWnd)
{
- HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
Child = IntGetWindowObject(*phWnd);
- NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
- NtGdiOffsetRgn(hRgnTemp,
- Window->WindowRect.left - Child->WindowRect.left,
- Window->WindowRect.top - Child->WindowRect.top);
- IntInvalidateWindows(Child, hRgnTemp, Flags);
- NtGdiDeleteObject(hRgnTemp);
+ if ((Child->Style & (WS_VISIBLE | WS_MINIMIZE)) == WS_VISIBLE)
+ {
+ HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
+ Child = IntGetWindowObject(*phWnd);
+ NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
+ NtGdiOffsetRgn(hRgnTemp,
+ Window->WindowRect.left - Child->WindowRect.left,
+ Window->WindowRect.top - Child->WindowRect.top);
+ IntInvalidateWindows(Child, hRgnTemp, Flags);
+ NtGdiDeleteObject(hRgnTemp);
+ }
IntReleaseWindowObject(Child);
}
ExFreePool(List);
}
}
-VOID FASTCALL
-IntValidateParent(PWINDOW_OBJECT Child)
-{
- HWND Parent;
- PWINDOW_OBJECT ParentWindow;
+/*
+ * IntIsWindowDrawable
+ *
+ * Remarks
+ * Window is drawable when it is visible, all parents are not
+ * minimized, and it is itself not minimized.
+ */
- Parent = NtUserGetAncestor(Child->Self, GA_PARENT);
- while (Parent && Parent != IntGetDesktopWindow())
+BOOL FASTCALL
+IntIsWindowDrawable(PWINDOW_OBJECT Window)
+{
+ for (; Window; Window = Window->Parent)
{
- ParentWindow = IntGetWindowObject(Parent);
- if (ParentWindow && !(ParentWindow->Style & WS_CLIPCHILDREN))
- {
- if (ParentWindow->UpdateRegion != 0)
- {
- INT OffsetX, OffsetY;
-
- /*
- * 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(Child->UpdateRegion, OffsetX, OffsetY );
- NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion,
- Child->UpdateRegion, RGN_DIFF);
- NtGdiOffsetRgn(Child->UpdateRegion, -OffsetX, -OffsetY);
- }
- }
- IntReleaseWindowObject(ParentWindow);
- Parent = NtUserGetAncestor(Parent, GA_PARENT);
+ if ((Window->Style & (WS_VISIBLE | WS_MINIMIZE)) != WS_VISIBLE)
+ return FALSE;
}
+
+ return TRUE;
}
/*
* Validation of passed parameters.
*/
- if ((Flags & (RDW_VALIDATE | RDW_INVALIDATE)) == (RDW_VALIDATE | RDW_INVALIDATE))
+ if (!IntIsWindowDrawable(Window) ||
+ (Flags & (RDW_VALIDATE | RDW_INVALIDATE)) ==
+ (RDW_VALIDATE | RDW_INVALIDATE))
{
return FALSE;
}
* Validate parent covered by region.
*/
- if (Window->UpdateRegion != NULL && Flags & RDW_UPDATENOW)
+ if (Window->UpdateRegion != NULL && Flags & (RDW_ERASENOW | RDW_VALIDATE))
{
IntValidateParent(Window);
}
CurrentEntry = CurrentEntry->Flink)
{
Window = CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, ThreadListEntry);
+ if (Window->Parent != NULL && !IntIsDesktopWindow(Window->Parent))
+ {
+ continue;
+ }
if (Window->Style & WS_VISIBLE)
{
hFoundWnd = IntFindWindowToRepaint(Window->Self, Thread);
ExAcquireFastMutex(&Window->ChildrenListLock);
-#if 0
for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
if (Child->Style & WS_VISIBLE &&
if (hFoundWnd == NULL)
{
-#endif
for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
if (Child->Style & WS_VISIBLE)
break;
}
}
-#if 0
}
-#endif
ExReleaseFastMutex(&Window->ChildrenListLock);
IntReleaseWindowObject(Window);
}
BOOL FASTCALL
-IntGetPaintMessage(PWINDOW_OBJECT Wnd, PW32THREAD Thread, MSG *Message)
+IntGetPaintMessage(PWINDOW_OBJECT Wnd, PW32THREAD Thread, MSG *Message,
+ BOOL Remove)
{
PWINDOW_OBJECT Window;
+ PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
+
+ if (!MessageQueue->PaintPosted)
+ return FALSE;
if (Wnd)
Message->hwnd = IntFindWindowToRepaint(Wnd->Self, PsGetWin32Thread());
if (Message->hwnd == NULL)
{
- PUSER_MESSAGE_QUEUE MessageQueue;
-
DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
- MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
- ExAcquireFastMutex(&MessageQueue->Lock);
- DPRINT1("Current paint count: %d\n", MessageQueue->PaintCount);
- MessageQueue->PaintCount = 0;
- MessageQueue->PaintPosted = FALSE;
- ExReleaseFastMutex(&MessageQueue->Lock);
return FALSE;
}
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
Message->message = WM_NCPAINT;
- Message->wParam = (WPARAM)IntGetNCUpdateRegion(Window);
+ Message->wParam = (WPARAM)IntGetNCUpdateRegion(Window, Remove);
Message->lParam = 0;
} else
{
Message->message = WM_PAINT;
Message->wParam = Message->lParam = 0;
- if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
+ if (Remove && Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
if (Window->UpdateRegion == NULL)
return NULL;
}
+/* IntRedrawWindow(Window, NULL, 0, RDW_NOINTERNALPAINT | RDW_VALIDATE | RDW_NOCHILDREN);*/
if (Window->UpdateRegion != NULL)
{
MsqDecPaintCountQueue(Window->MessageQueue);
+ IntValidateParent(Window);
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
NTSTATUS Status;
PWINDOW_OBJECT Wnd;
- if (!(Wnd = IntGetWindowObject(hWnd)))
+ if (!(Wnd = IntGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
{
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: winpos.c,v 1.44 2003/11/20 21:21:29 navaraf Exp $
+/* $Id: winpos.c,v 1.45 2003/11/21 17:01:16 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
return FALSE;
}
- if (Window->Flags & WINDOWOBJECT_MAPPING)
- {
- /* FIXME: SetLastWin32Error */
- return FALSE;
- }
-
- Window->Flags |= WINDOWOBJECT_MAPPING;
-
WinPos.hwnd = Wnd;
WinPos.hwndInsertAfter = WndInsertAfter;
WinPos.x = x;
RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
Window->Style &= ~WS_VISIBLE;
}
- else
+ else if (WinPos.flags & SWP_SHOWWINDOW)
{
Window->Style |= WS_VISIBLE;
}
}
else
{
- IntRedrawWindow(Window, NULL, NULL,
+ IntRedrawWindow(Window, NULL, 0,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
if (!(WinPos.flags & SWP_NOREDRAW))
{
- /* FIXME: Call IntRedrawWindow to erase *all* touched windows. */
IntRedrawWindow(Window, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW);
}
/* FIXME: Check some conditions before doing this. */
IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
- Window->Flags &= ~WINDOWOBJECT_MAPPING;
-
IntReleaseWindowObject(Window);
return TRUE;
UINT Swp = 0;
RECT NewPos;
BOOLEAN ShowFlag;
- HRGN VisibleRgn;
+// HRGN VisibleRgn;
Status =
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
*/
}
+#if 1
+ /* We can't activate a child window */
+ if ((Window->Style & WS_CHILD) &&
+ !(Window->ExStyle & WS_EX_MDICHILD))
+ {
+ Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ }
+
+ WinPosSetWindowPos(Window->Self, HWND_TOP, NewPos.left, NewPos.top,
+ NewPos.right, NewPos.bottom, LOWORD(Swp));
+
+ if (Cmd == SW_HIDE)
+ {
+ /* FIXME: This will cause the window to be activated irrespective
+ * of whether it is owned by the same thread. Has to be done
+ * asynchronously.
+ */
+
+ if (Window->Self == IntGetActiveWindow())
+ {
+ WinPosActivateOtherWindow(Window);
+ }
+
+ /* Revert focus to parent */
+ if (Wnd == IntGetFocusWindow() ||
+ IntIsChildWindow(Wnd, IntGetFocusWindow()))
+ {
+ IntSetFocusWindow(Window->Parent->Self);
+ }
+ }
+
+ /* FIXME: Check for window destruction. */
+ /* Show title for minimized windows. */
+ if (Window->Style & WS_MINIMIZE)
+ {
+ WinPosShowIconTitle(Window, TRUE);
+ }
+#else
if (Window->Style & WS_CHILD &&
!IntIsWindowVisible(Window->Parent->Self) &&
(Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
WinPosShowIconTitle(Window, TRUE);
}
}
+#endif
if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
{