Painting bug fixes.

svn path=/trunk/; revision=7264
This commit is contained in:
Filip Navara 2003-12-27 15:09:51 +00:00
parent 6168d52ff8
commit ca3586e5a9
6 changed files with 133 additions and 210 deletions

View file

@ -1,4 +1,4 @@
/* $Id: desktopbg.c,v 1.3 2003/12/22 15:30:21 navaraf Exp $
/* $Id: desktopbg.c,v 1.4 2003/12/27 15:09:51 navaraf Exp $
*
* reactos/subsys/csrss/win32csr/desktopbg.c
*
@ -50,7 +50,7 @@ DtbgWindowProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT PS;
BeginPaint(Wnd, &PS);
PaintDesktop((HDC)PS.hdc);
/* No need to paint, already done in WM_ERASEBKGND. */
EndPaint(Wnd, &PS);
Result = 0;
}

View file

@ -58,6 +58,7 @@ typedef struct _WINDOW_OBJECT
UINT IDMenu;
/* Handle of region of the window to be updated. */
HANDLE UpdateRegion;
HANDLE NCUpdateRegion;
/* Pointer to the owning thread's message queue. */
PUSER_MESSAGE_QUEUE MessageQueue;
struct _WINDOW_OBJECT* FirstChild;

View file

@ -16,7 +16,7 @@
* 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.53 2003/12/26 22:52:11 gvg Exp $
* $Id: painting.c,v 1.54 2003/12/27 15:09:51 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -54,6 +54,8 @@
#define NDEBUG
#include <debug.h>
/* #define FIN_DEBUG */
/* PRIVATE FUNCTIONS **********************************************************/
VOID FASTCALL
@ -101,17 +103,19 @@ IntValidateParent(PWINDOW_OBJECT Child)
*
* 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 if the Remove is set
* to TRUE.
* as valid, clears the WINDOWOBJECT_NEED_NCPAINT flag.
*/
HRGN FASTCALL
IntGetNCUpdateRegion(PWINDOW_OBJECT Window, BOOL Remove)
IntGetNCUpdateRegion(PWINDOW_OBJECT Window)
{
HRGN WindowRgn;
HRGN NonclientRgn;
/*
* Generate the update region.
*/
WindowRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
NtGdiOffsetRgn(WindowRgn,
-Window->WindowRect.left,
@ -123,16 +127,16 @@ IntGetNCUpdateRegion(PWINDOW_OBJECT Window, BOOL Remove)
NtGdiDeleteObject(NonclientRgn);
NonclientRgn = NULL;
}
if (Remove)
/*
* Remove the nonclient region from the standard update region.
*/
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
WindowRgn, RGN_AND) == NULLREGION)
{
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
WindowRgn, RGN_AND) == NULLREGION)
{
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue);
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
return NonclientRgn;
@ -159,13 +163,24 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)IntGetNCUpdateRegion(Window, TRUE), 0);
IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)Window->NCUpdateRegion, 0);
Window->NCUpdateRegion = NULL;
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue);
}
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
{
if (Window->UpdateRegion)
{
#ifdef FIN_DEBUG
{
RECT TempRect;
UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
DPRINT1("Sending WM_ERASEBKGND[1]: %d,%d-%d,%d\n",
TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
}
#endif
hDC = NtUserGetDCEx(hWnd, 0, DCX_CACHE | DCX_USESTYLE |
DCX_INTERSECTUPDATE);
if (hDC != NULL)
@ -184,6 +199,14 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
if (Window->UpdateRegion != NULL ||
Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
#ifdef FIN_DEBUG
{
RECT TempRect;
UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
DPRINT1("Sending WM_PAINT[1]: %d,%d-%d,%d\n",
TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
}
#endif
IntSendMessage(hWnd, WM_PAINT, 0, 0);
if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{
@ -341,6 +364,22 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags,
IntValidateParent(Window);
}
/*
* Split the nonclient update region.
*/
if (Window->NCUpdateRegion == NULL)
{
Window->NCUpdateRegion = IntGetNCUpdateRegion(Window);
}
else
{
HRGN hRgnNonClient = IntGetNCUpdateRegion(Window);
NtGdiCombineRgn(Window->NCUpdateRegion, Window->NCUpdateRegion,
hRgnNonClient, RGN_OR);
NtGdiDeleteObject(hRgnNonClient);
}
/*
* Process children if needed
*/
@ -360,8 +399,10 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags,
{
continue;
}
if ((Child->Style & (WS_VISIBLE | WS_MINIMIZE)) == WS_VISIBLE)
if (Child->Style & WS_VISIBLE)
{
RECT TempRect;
/*
* Recursive call to update children UpdateRegion
*/
@ -375,20 +416,22 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags,
/*
* Update our UpdateRegion depending on children
*/
NtGdiCombineRgn(hRgnTemp, Child->UpdateRegion, 0, RGN_COPY);
NtGdiOffsetRgn(hRgnTemp,
Child->WindowRect.left - Window->WindowRect.left,
Child->WindowRect.top - Window->WindowRect.top);
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
NtGdiOffsetRgn(hRgnWindow,
-Window->WindowRect.left,
-Window->WindowRect.top);
NtGdiCombineRgn(hRgnTemp, hRgnTemp, hRgnWindow, RGN_AND);
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
hRgnTemp, RGN_DIFF) == NULLREGION)
if (Window->UpdateRegion != NULL)
{
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
NtGdiCombineRgn(hRgnTemp, Child->UpdateRegion, 0, RGN_COPY);
NtGdiCombineRgn(hRgnTemp, hRgnTemp, Child->NCUpdateRegion, RGN_OR);
NtGdiOffsetRgn(hRgnTemp,
Child->WindowRect.left - Window->WindowRect.left,
Child->WindowRect.top - Window->WindowRect.top);
UnsafeIntGetRgnBox(hRgnTemp, &TempRect);
if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion,
hRgnTemp, RGN_DIFF) == NULLREGION)
{
NtGdiDeleteObject(Window->UpdateRegion);
Window->UpdateRegion = NULL;
}
}
NtGdiDeleteObject(hRgnTemp);
}
@ -435,7 +478,7 @@ IntIsWindowDrawable(PWINDOW_OBJECT Window)
{
for (; Window; Window = Window->Parent)
{
if ((Window->Style & (WS_VISIBLE | WS_MINIMIZE)) != WS_VISIBLE)
if (!(Window->Style & WS_VISIBLE))
return FALSE;
}
@ -661,10 +704,24 @@ IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message,
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{
Message->message = WM_NCPAINT;
Message->wParam = (WPARAM)IntGetNCUpdateRegion(Window, Remove);
Message->wParam = (WPARAM)Window->NCUpdateRegion;
Message->lParam = 0;
if (Remove)
{
Window->NCUpdateRegion = NULL;
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue);
}
} else
{
#ifdef FIN_DEBUG
{
RECT TempRect;
UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
DPRINT1("Sending WM_PAINT[2]: %d,%d-%d,%d\n",
TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
}
#endif
Message->message = WM_PAINT;
Message->wParam = Message->lParam = 0;
if (Remove && Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
@ -757,6 +814,16 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs)
}
/* IntRedrawWindow(Window, NULL, 0, RDW_NOINTERNALPAINT | RDW_VALIDATE | RDW_NOCHILDREN);*/
#ifdef FIN_DEBUG
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
{
RECT TempRect;
UnsafeIntGetRgnBox(Window->UpdateRegion, &TempRect);
DPRINT1("Sending WM_ERASEBKGND[2]: %d,%d-%d,%d\n",
TempRect.left, TempRect.top, TempRect.right, TempRect.bottom);
}
#endif
if (Window->UpdateRegion != NULL)
{
MsqDecPaintCountQueue(Window->MessageQueue);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: vis.c,v 1.14 2003/12/12 18:59:24 weiden Exp $
* $Id: vis.c,v 1.15 2003/12/27 15:09:51 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -210,137 +210,24 @@ VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
return VisRgn;
}
static VOID FASTCALL
GetUncoveredArea(HRGN Uncovered, PWINDOW_OBJECT Parent, PWINDOW_OBJECT TargetChild,
BOOL IncludeTarget)
{
PWINDOW_OBJECT Child;
BOOL Passed;
HRGN Covered;
Passed = FALSE;
ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
Child = Parent->FirstChild;
while (! Passed && Child)
{
if (0 != (Child->Style & WS_VISIBLE) && (Child != TargetChild || IncludeTarget))
{
Covered = UnsafeIntCreateRectRgnIndirect(&Child->WindowRect);
NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF);
NtGdiDeleteObject(Covered);
}
if (Child == TargetChild)
{
Passed = TRUE;
}
Child = Child->NextSibling;
}
ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
}
VOID FASTCALL
VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
HRGN NewlyExposed)
{
PWINDOW_OBJECT DesktopWindow;
PWINDOW_OBJECT Parent;
PWINDOW_OBJECT Sibling;
PWINDOW_OBJECT TopLevel;
HRGN Uncovered;
HRGN Repaint;
HRGN DirtyRgn;
HRGN ExposedWindow;
HRGN Covered;
INT RgnType;
POINT Offset;
DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
Uncovered = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect);
if (Window->Style & WS_CHILD)
{
/* Determine our toplevel window */
TopLevel = Window;
while (TopLevel->Style & WS_CHILD)
{
TopLevel = TopLevel->Parent;
}
GetUncoveredArea(Uncovered, DesktopWindow, TopLevel, FALSE);
Parent = Window->Parent;
}
else
{
Parent = DesktopWindow;
}
GetUncoveredArea(Uncovered, Parent, Window, TRUE);
ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
Sibling = Window->NextSibling;
while (Sibling)
{
if (0 != (Sibling->Style & WS_VISIBLE))
{
Offset.x = - Sibling->WindowRect.left;
Offset.y = - Sibling->WindowRect.top;
DirtyRgn = REGION_CropRgn(NULL, Uncovered, &Sibling->WindowRect, &Offset);
Offset.x = Window->WindowRect.left - Sibling->WindowRect.left;
Offset.y = Window->WindowRect.top - Sibling->WindowRect.top;
ExposedWindow = REGION_CropRgn(NULL, NewlyExposed, NULL, &Offset);
RgnType = NtGdiCombineRgn(DirtyRgn, DirtyRgn, ExposedWindow, RGN_AND);
if (NULLREGION != RgnType && ERROR != RgnType)
{
NtGdiOffsetRgn(DirtyRgn,
Sibling->WindowRect.left - Sibling->ClientRect.left,
Sibling->WindowRect.top - Sibling->ClientRect.top);
IntRedrawWindow(Sibling, NULL, DirtyRgn,
RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
RDW_ALLCHILDREN);
}
Covered = UnsafeIntCreateRectRgnIndirect(&Sibling->WindowRect);
NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF);
NtGdiDeleteObject(Covered);
NtGdiDeleteObject(ExposedWindow);
NtGdiDeleteObject(DirtyRgn);
}
Sibling = Sibling->NextSibling;
}
ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
if (Window->Style & WS_CHILD)
{
Offset.x = - Parent->WindowRect.left;
Offset.y = - Parent->WindowRect.top;
DirtyRgn = REGION_CropRgn(NULL, Uncovered, &Parent->WindowRect, &Offset);
Offset.x = Window->WindowRect.left - Parent->WindowRect.left;
Offset.y = Window->WindowRect.top - Parent->WindowRect.top;
ExposedWindow = REGION_CropRgn(NULL, NewlyExposed, NULL, &Offset);
RgnType = NtGdiCombineRgn(DirtyRgn, DirtyRgn, ExposedWindow, RGN_AND);
if (NULLREGION != RgnType && ERROR != RgnType)
{
NtGdiOffsetRgn(DirtyRgn,
Parent->WindowRect.left - Parent->ClientRect.left,
Parent->WindowRect.top - Parent->ClientRect.top);
IntRedrawWindow(Parent, NULL, DirtyRgn,
RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
RDW_NOCHILDREN);
}
NtGdiDeleteObject(ExposedWindow);
NtGdiDeleteObject(DirtyRgn);
}
else
{
Repaint = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(Repaint, NewlyExposed, NULL, RGN_COPY);
NtGdiOffsetRgn(Repaint, Window->WindowRect.left, Window->WindowRect.top);
NtGdiCombineRgn(Repaint, Repaint, Uncovered, RGN_AND);
NtUserRedrawWindow(DesktopWindow->Self, NULL, Repaint,
RDW_UPDATENOW | RDW_INVALIDATE | RDW_NOCHILDREN);
NtGdiDeleteObject(Repaint);
}
NtGdiDeleteObject(Uncovered);
HRGN Temp;
Temp = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
if (Window->Parent != NULL)
{
NtGdiOffsetRgn(Temp,
Window->WindowRect.left - Window->Parent->ClientRect.left,
Window->WindowRect.top - Window->Parent->ClientRect.top);
}
IntRedrawWindow(Window->Parent, NULL, Temp,
RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
RDW_ALLCHILDREN);
NtGdiDeleteObject(Temp);
}
/* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: windc.c,v 1.47 2003/12/23 08:48:59 navaraf Exp $
/* $Id: windc.c,v 1.48 2003/12/27 15:09:51 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -433,21 +433,12 @@ NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
if (Dce->hClipRgn && Window->UpdateRegion)
{
NtGdiCombineRgn(Dce->hClipRgn, Window->UpdateRegion, NULL, RGN_COPY);
NtGdiOffsetRgn(Dce->hClipRgn,
Window->WindowRect.left - Window->ClientRect.left,
Window->WindowRect.top - Window->ClientRect.top);
/*
if (!(Flags & DCX_WINDOW))
{
HRGN ClientRgn = NtGdiCreateRectRgnIndirect(&Window->ClientRect);
NtGdiOffsetRgn(ClientRgn,
-Window->ClientRect.left,
-Window->ClientRect.top);
NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, ClientRgn, RGN_AND);
NtGdiDeleteObject(ClientRgn);
NtGdiOffsetRgn(Dce->hClipRgn,
Window->WindowRect.left - Window->ClientRect.left,
Window->WindowRect.top - Window->ClientRect.top);
}
*/
}
Flags |= DCX_INTERSECTRGN;
}
@ -457,13 +448,15 @@ NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
if (!(Flags & DCX_WINDOW))
{
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
NtGdiOffsetRgn(Dce->hClipRgn, -Window->ClientRect.left,
-Window->ClientRect.top);
}
else
{
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left,
-Window->WindowRect.top);
}
NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left,
-Window->WindowRect.top);
}
else if (NULL != ClipRegion)
{
@ -485,8 +478,8 @@ NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
Parent = Window->Parent;
if (Window->Style & WS_VISIBLE &&
!(Parent->Style & WS_MINIMIZE))
if (Window->Style & WS_VISIBLE /*&&
!(Parent->Style & WS_MINIMIZE)*/)
{
if (Parent->Style & WS_CLIPSIBLINGS)
{

View file

@ -16,7 +16,7 @@
* 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.74 2003/12/26 22:52:12 gvg Exp $
/* $Id: winpos.c,v 1.75 2003/12/27 15:09:51 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -238,6 +238,8 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
{
WindowObject->Flags &= ~WINDOWOBJECT_RESTOREMAX;
}
IntRedrawWindow(WindowObject, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
RDW_NOINTERNALPAINT);
WindowObject->Style |= WS_MINIMIZE;
WinPosFindIconPos(WindowObject, &InternalPos->IconPos);
NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
@ -381,33 +383,6 @@ WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
return 0; //FIXME: what does it return?
}
#if 0
BOOL STATIC FASTCALL
WinPosChangeActiveWindow(HWND hWnd, BOOL MouseMsg)
{
PWINDOW_OBJECT WindowObject;
WindowObject = IntGetWindowObject(hWnd);
if (WindowObject == NULL)
{
return FALSE;
}
#if 0
IntSendMessage(hWnd,
WM_ACTIVATE,
MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
(WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
(LPARAM)IntGetDesktopWindow()); /* FIXME: Previous active window */
#endif
IntSetForegroundWindow(WindowObject);
IntReleaseWindowObject(WindowObject);
return TRUE;
}
#endif
LONG STATIC FASTCALL
WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
RECT* WindowRect, RECT* ClientRect)
@ -532,10 +507,6 @@ WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
HWND FASTCALL
WinPosDoOwnedPopups(HWND hWnd, HWND hWndInsertAfter)
{
#if 0
/* FIXME */
return hWndInsertAfter;
#endif
HWND *List = NULL;
HWND Owner = NtUserGetWindow(hWnd, GW_OWNER);
LONG Style = NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE);
@ -940,6 +911,10 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
{
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
}
if (Window->NCUpdateRegion != NULL)
{
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->NCUpdateRegion, RGN_DIFF);
}
/*
* Now, get the bounding box of the copy region. If it's empty