- Painting bugfixes.

svn path=/trunk/; revision=6725
This commit is contained in:
Filip Navara 2003-11-20 09:18:49 +00:00
parent 669a79e12b
commit 06c149f1f1
4 changed files with 381 additions and 343 deletions

View file

@ -1,4 +1,4 @@
/* $Id: vis.h,v 1.3 2003/11/19 09:10:35 navaraf Exp $ /* $Id: vis.h,v 1.4 2003/11/20 09:18:49 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem * PROJECT: ReactOS Win32k subsystem
@ -21,7 +21,7 @@ VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
VOID FASTCALL VOID FASTCALL
VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window, VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
HRGN UncoveredRgn, BOOL Redraw); HRGN UncoveredRgn);
VOID FASTCALL VOID FASTCALL
VIS_RepaintDesktop(HWND Desktop, HRGN RepaintRgn); VIS_RepaintDesktop(HWND Desktop, HRGN RepaintRgn);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: vis.c,v 1.9 2003/11/19 09:10:36 navaraf Exp $ * $Id: vis.c,v 1.10 2003/11/20 09:18:49 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -251,7 +251,7 @@ GetUncoveredArea(HRGN Uncovered, PWINDOW_OBJECT Parent, PWINDOW_OBJECT TargetChi
VOID FASTCALL VOID FASTCALL
VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window, VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
HRGN NewlyExposed, BOOL Redraw) HRGN NewlyExposed)
{ {
PWINDOW_OBJECT DesktopWindow; PWINDOW_OBJECT DesktopWindow;
PWINDOW_OBJECT Parent; PWINDOW_OBJECT Parent;
@ -304,8 +304,7 @@ VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
NtGdiOffsetRgn(DirtyRgn, -Sibling->ClientRect.left, -Sibling->ClientRect.top); NtGdiOffsetRgn(DirtyRgn, -Sibling->ClientRect.left, -Sibling->ClientRect.top);
IntRedrawWindow(Sibling, NULL, DirtyRgn, IntRedrawWindow(Sibling, NULL, DirtyRgn,
RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
RDW_ALLCHILDREN | RDW_ALLCHILDREN);
(Redraw ? RDW_ERASENOW | RDW_UPDATENOW : 0));
} }
Covered = UnsafeIntCreateRectRgnIndirect(&Sibling->WindowRect); Covered = UnsafeIntCreateRectRgnIndirect(&Sibling->WindowRect);
NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF); NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF);
@ -333,8 +332,7 @@ VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
-Parent->ClientRect.top); -Parent->ClientRect.top);
IntRedrawWindow(Parent, NULL, DirtyRgn, IntRedrawWindow(Parent, NULL, DirtyRgn,
RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
RDW_NOCHILDREN | RDW_NOCHILDREN);
(Redraw ? RDW_ERASENOW | RDW_UPDATENOW : 0));
} }
NtGdiDeleteObject(ExposedWindow); NtGdiDeleteObject(ExposedWindow);
NtGdiDeleteObject(DirtyRgn); NtGdiDeleteObject(DirtyRgn);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: window.c,v 1.137 2003/11/19 09:10:36 navaraf Exp $ /* $Id: window.c,v 1.138 2003/11/20 09:18:49 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -675,7 +675,7 @@ IntInitDesktopWindow(ULONG Width, ULONG Height)
DesktopWindow->ClientRect = DesktopWindow->WindowRect; DesktopWindow->ClientRect = DesktopWindow->WindowRect;
DesktopRgn = UnsafeIntCreateRectRgnIndirect(&(DesktopWindow->WindowRect)); DesktopRgn = UnsafeIntCreateRectRgnIndirect(&(DesktopWindow->WindowRect));
VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, DesktopWindow, DesktopRgn, TRUE); VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, DesktopWindow, DesktopRgn);
NtGdiDeleteObject(DesktopRgn); NtGdiDeleteObject(DesktopRgn);
IntReleaseWindowObject(DesktopWindow); IntReleaseWindowObject(DesktopWindow);
} }
@ -817,7 +817,7 @@ IntSetFocusWindow(HWND hWnd)
if (hWnd != (HWND)0) if (hWnd != (HWND)0)
{ {
WindowObject = IntGetWindowObject(hWnd); WindowObject = IntGetWindowObject(hWnd);
if (!WindowObject) if (!WindowObject || IntIsDesktopWindow(WindowObject))
{ {
DPRINT("Bad window handle 0x%x\n", hWnd); DPRINT("Bad window handle 0x%x\n", hWnd);
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
@ -1811,18 +1811,19 @@ NtUserDestroyWindow(HWND Wnd)
} }
/* Recursively destroy owned windows */ /* Recursively destroy owned windows */
#if 0 /* FIXME */ #if 1 /* FIXME */
if (! isChild) if (! isChild)
{ {
for (;;) for (;;)
{ {
int i;
BOOL GotOne = FALSE; BOOL GotOne = FALSE;
HWND *Children; HWND *Children;
HWND *ChildHandle; HWND *ChildHandle;
PWINDOW_OBJECT Child; PWINDOW_OBJECT Child, Desktop;
Children = IntWinListChildren(IntGetWindowObject(IntGetDesktopWindow()); Desktop = IntGetWindowObject(IntGetDesktopWindow());
Children = IntWinListChildren(Desktop);
IntReleaseWindowObject(Desktop);
if (Children) if (Children)
{ {
for (ChildHandle = Children; *ChildHandle; ++ChildHandle) for (ChildHandle = Children; *ChildHandle; ++ChildHandle)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: winpos.c,v 1.42 2003/11/19 09:10:36 navaraf Exp $ /* $Id: winpos.c,v 1.43 2003/11/20 09:18:49 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -605,6 +605,109 @@ WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
ExReleaseFastMutexUnsafe(&Window->ChildrenListLock); ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
} }
/*
* WinPosFixupSWPFlags
*
* Fix redundant flags and values in the WINDOWPOS structure.
*/
BOOL FASTCALL
WinPosFixupFlags(WINDOWPOS *WinPos, PWINDOW_OBJECT Window)
{
if (Window->Style & WS_VISIBLE)
{
WinPos->flags &= ~SWP_SHOWWINDOW;
}
else
{
WinPos->flags &= ~SWP_HIDEWINDOW;
if (!(WinPos->flags & SWP_SHOWWINDOW))
WinPos->flags |= SWP_NOREDRAW;
}
WinPos->cx = max(WinPos->cx, 0);
WinPos->cy = max(WinPos->cy, 0);
/* Check for right size */
if (Window->WindowRect.right - Window->WindowRect.left == WinPos->cx &&
Window->WindowRect.bottom - Window->WindowRect.top == WinPos->cy)
{
WinPos->flags |= SWP_NOSIZE;
}
/* Check for right position */
if (Window->WindowRect.left == WinPos->x &&
Window->WindowRect.top == WinPos->y)
{
WinPos->flags |= SWP_NOMOVE;
}
/* FIXME: We don't have NtUserGetForegroundWindow yet. */
#if 0
if (WinPos->hwnd == NtUserGetForegroundWindow())
{
WinPos->flags |= SWP_NOACTIVATE; /* Already active */
}
else
#endif
if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
{
/* Bring to the top when activating */
if (!(WinPos->flags & SWP_NOACTIVATE))
{
WinPos->flags &= ~SWP_NOZORDER;
WinPos->hwndInsertAfter = HWND_TOP;
return TRUE;
}
}
/* Check hwndInsertAfter */
if (!(WinPos->flags & SWP_NOZORDER))
{
/* Fix sign extension */
if (WinPos->hwndInsertAfter == (HWND)0xffff)
{
WinPos->hwndInsertAfter = HWND_TOPMOST;
}
else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
{
WinPos->hwndInsertAfter = HWND_NOTOPMOST;
}
/* FIXME: TOPMOST not supported yet */
if ((WinPos->hwndInsertAfter == HWND_TOPMOST) ||
(WinPos->hwndInsertAfter == HWND_NOTOPMOST))
{
WinPos->hwndInsertAfter = HWND_TOP;
}
/* hwndInsertAfter must be a sibling of the window */
if ((WinPos->hwndInsertAfter != HWND_TOP) &&
(WinPos->hwndInsertAfter != HWND_BOTTOM))
{
if (NtUserGetAncestor(WinPos->hwndInsertAfter, GA_PARENT) !=
Window->Parent)
{
return FALSE;
}
else
{
/*
* We don't need to change the Z order of hwnd if it's already
* inserted after hwndInsertAfter or when inserting hwnd after
* itself.
*/
if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
(WinPos->hwnd == NtUserGetWindow(WinPos->hwndInsertAfter, GW_HWNDNEXT)))
{
WinPos->flags |= SWP_NOZORDER;
}
}
}
}
return TRUE;
}
/* x and y are always screen relative */ /* x and y are always screen relative */
BOOLEAN STDCALL BOOLEAN STDCALL
@ -612,7 +715,6 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
INT cy, UINT flags) INT cy, UINT flags)
{ {
PWINDOW_OBJECT Window; PWINDOW_OBJECT Window;
NTSTATUS Status;
WINDOWPOS WinPos; WINDOWPOS WinPos;
RECT NewWindowRect; RECT NewWindowRect;
RECT NewClientRect; RECT NewClientRect;
@ -623,7 +725,6 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
HRGN CopyRgn = NULL; HRGN CopyRgn = NULL;
ULONG WvrFlags = 0; ULONG WvrFlags = 0;
RECT OldWindowRect, OldClientRect; RECT OldWindowRect, OldClientRect;
UINT FlagsEx = 0;
int RgnType; int RgnType;
HDC Dc; HDC Dc;
RECT CopyRect; RECT CopyRect;
@ -632,84 +733,16 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
/* FIXME: Get current active window from active queue. */ /* FIXME: Get current active window from active queue. */
/* Check if the window is for a desktop. */ /* Check if the window is for a desktop. */
if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow) if (Wnd == IntGetDesktopWindow())
{ {
return(FALSE);
}
Status =
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
Wnd,
otWindow,
(PVOID*)&Window);
if (!NT_SUCCESS(Status))
{
return(FALSE);
}
/* Fix up the flags. */
if (Window->Style & WS_VISIBLE)
{
flags &= ~SWP_SHOWWINDOW;
}
else
{
if (!(flags & SWP_SHOWWINDOW))
{
flags |= SWP_NOREDRAW;
}
flags &= ~SWP_HIDEWINDOW;
}
cx = max(cx, 0);
cy = max(cy, 0);
if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
(Window->WindowRect.bottom - Window->WindowRect.top) == cy)
{
flags |= SWP_NOSIZE;
}
if (Window->WindowRect.left == x && Window->WindowRect.top == y)
{
flags |= SWP_NOMOVE;
}
if (Window->Flags & WIN_NCACTIVATED)
{
flags |= SWP_NOACTIVATE;
}
else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
{
if (!(flags & SWP_NOACTIVATE))
{
flags &= ~SWP_NOZORDER;
WndInsertAfter = HWND_TOP;
}
}
if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
{
WndInsertAfter = HWND_TOP;
}
if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
{
if (NtUserGetAncestor(WndInsertAfter, GA_PARENT) != Window->Parent)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
else
Window = IntGetWindowObject(Wnd);
if (!Window)
{ {
/* SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
* Don't need to change the Zorder of hwnd if it's already inserted return FALSE;
* after hwndInsertAfter or when inserting hwnd after itself.
*/
if (Wnd == WndInsertAfter ||
Wnd == NtUserGetWindow(WndInsertAfter, GW_HWNDNEXT))
{
flags |= SWP_NOZORDER;
}
}
} }
WinPos.hwnd = Wnd; WinPos.hwnd = Wnd;
@ -719,55 +752,57 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
WinPos.cx = cx; WinPos.cx = cx;
WinPos.cy = cy; WinPos.cy = cy;
WinPos.flags = flags; WinPos.flags = flags;
if (0 != (Window->Style & WS_CHILD)) if (Window->Style & WS_CHILD)
{ {
WinPos.x -= Window->Parent->ClientRect.left; WinPos.x -= Window->Parent->ClientRect.left;
WinPos.y -= Window->Parent->ClientRect.top; WinPos.y -= Window->Parent->ClientRect.top;
} }
/* Fix up the flags. */
if (!WinPosFixupFlags(&WinPos, Window))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
IntReleaseWindowObject(Window);
return FALSE;
}
WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
/* Does the window still exist? */
if (!IntIsWindow(WinPos.hwnd))
{
/* FIXME: SetLastWin32Error */
return FALSE;
}
if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
SWP_NOZORDER && SWP_NOZORDER &&
NtUserGetAncestor(WinPos.hwnd, GA_PARENT) == NtUserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
PsGetWin32Thread()->Desktop->DesktopWindow)
{ {
WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter); WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter);
} }
/* FIXME: Adjust flags based on WndInsertAfter */
/* Compute the visible region before the window position is changed */ /* Compute the visible region before the window position is changed */
if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) && if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
(SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
{ {
if (Window->Style & WS_CLIPCHILDREN) VisBefore = VIS_ComputeVisibleRegion(
{ PsGetWin32Thread()->Desktop, Window, FALSE,
VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window->Style & WS_CLIPCHILDREN, Window->Style & WS_CLIPSIBLINGS);
Window, FALSE, FALSE, TRUE);
} if (UnsafeIntGetRgnBox(VisBefore, &TempRect) == NULLREGION)
else
{
VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
Window, FALSE, FALSE, FALSE);
}
if (NULLREGION == UnsafeIntGetRgnBox(VisBefore, &TempRect))
{ {
NtGdiDeleteObject(VisBefore); NtGdiDeleteObject(VisBefore);
VisBefore = NULL; VisBefore = NULL;
} }
} }
WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
&NewClientRect);
/* /* Relink windows. (also take into account shell window in hwndShellWindow) */
* FIXME: Relink windows. (also take into account shell window in hwndShellWindow) if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != NtUserGetShellWindow())
*/
if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwndInsertAfter != WinPos.hwnd &&
WinPos.hwnd != NtUserGetShellWindow())
{ {
PWINDOW_OBJECT ParentWindow; PWINDOW_OBJECT ParentWindow;
PWINDOW_OBJECT InsertAfterWindow; PWINDOW_OBJECT InsertAfterWindow;
@ -795,7 +830,19 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
OldWindowRect = Window->WindowRect; OldWindowRect = Window->WindowRect;
OldClientRect = Window->ClientRect; OldClientRect = Window->ClientRect;
/* FIXME: Check for redrawing the whole client rect. */ if (OldClientRect.bottom - OldClientRect.top ==
NewClientRect.bottom - NewClientRect.top)
{
WvrFlags &= ~WVR_VREDRAW;
}
if (OldClientRect.right - OldClientRect.left ==
NewClientRect.right - NewClientRect.left)
{
WvrFlags &= ~WVR_HREDRAW;
}
/* FIXME: Actually do something with WVR_VALIDRECTS */
if (!(WinPos.flags & SWP_NOMOVE)) if (!(WinPos.flags & SWP_NOMOVE))
{ {
@ -803,58 +850,71 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
NewWindowRect.left - OldWindowRect.left, NewWindowRect.left - OldWindowRect.left,
NewWindowRect.top - OldWindowRect.top); NewWindowRect.top - OldWindowRect.top);
} }
Window->WindowRect = NewWindowRect; Window->WindowRect = NewWindowRect;
Window->ClientRect = NewClientRect; Window->ClientRect = NewClientRect;
if (WinPos.flags & SWP_SHOWWINDOW) if (!(WinPos.flags & SWP_SHOWWINDOW) && (WinPos.flags & SWP_HIDEWINDOW))
{
Window->Style |= WS_VISIBLE;
FlagsEx |= SWP_EX_PAINTSELF;
}
else if (WinPos.flags & SWP_HIDEWINDOW)
{ {
/* Clear the update region */
IntRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOFRAME |
RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
Window->Style &= ~WS_VISIBLE; Window->Style &= ~WS_VISIBLE;
} }
if (!(WinPos.flags & SWP_NOREDRAW))
{
/* Determine the new visible region */
if (Window->Style & WS_CLIPCHILDREN)
{
VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
Window, FALSE, FALSE, TRUE);
}
else else
{ {
VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window->Style |= WS_VISIBLE;
Window, FALSE, FALSE, FALSE);
} }
if (NULLREGION == UnsafeIntGetRgnBox(VisAfter, &TempRect))
#if 0
if (WvrFlags & WVR_REDRAW)
{
IntRedrawWindow(Window, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME);
}
#endif
if (!(WinPos.flags & SWP_NOACTIVATE))
{
WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
}
/* FIXME: Check some conditions before doing this. */
IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
/* Determine the new visible region */
VisAfter = VIS_ComputeVisibleRegion(
PsGetWin32Thread()->Desktop, Window, FALSE,
Window->Style & WS_CLIPCHILDREN, Window->Style & WS_CLIPSIBLINGS);
if (UnsafeIntGetRgnBox(VisAfter, &TempRect) == NULLREGION)
{ {
NtGdiDeleteObject(VisAfter); NtGdiDeleteObject(VisAfter);
VisAfter = NULL; VisAfter = NULL;
} }
/* Determine which pixels can be copied from the old window position /*
to the new. Those pixels must be visible in both the old and new * Determine which pixels can be copied from the old window position
position. Also, check the class style to see if the windows of this * to the new. Those pixels must be visible in both the old and new
class need to be completely repainted on (horizontal/vertical) size * position. Also, check the class style to see if the windows of this
change */ * class need to be completely repainted on (horizontal/vertical) size
if (NULL != VisBefore && NULL != VisAfter && ! (WinPos.flags & SWP_NOCOPYBITS) * change.
&& ((WinPos.flags & SWP_NOSIZE) */
|| ! (Window->Class->style & (CS_HREDRAW | CS_VREDRAW)))) if (VisBefore != NULL && VisAfter != NULL && !(WinPos.flags & SWP_NOCOPYBITS) &&
((WinPos.flags & SWP_NOSIZE) || !(Window->Class->style & (CS_HREDRAW | CS_VREDRAW))))
{ {
CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0); CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
/* If this is (also) a window resize, the whole nonclient area /*
needs to be repainted. So we limit the copy to the client area, * If this is (also) a window resize, the whole nonclient area
'cause there is no use in copying it (would possibly cause * needs to be repainted. So we limit the copy to the client area,
"flashing" too). However, if the copy region is already empty, * 'cause there is no use in copying it (would possibly cause
we don't have to crop (can't take anything away from an empty * "flashing" too). However, if the copy region is already empty,
region...) */ * we don't have to crop (can't take anything away from an empty
if (! (WinPos.flags & SWP_NOSIZE) * region...)
&& ERROR != RgnType && NULLREGION != RgnType) */
if (!(WinPos.flags & SWP_NOSIZE) && RgnType != ERROR &&
RgnType != NULLREGION)
{ {
RECT ORect = OldClientRect; RECT ORect = OldClientRect;
RECT NRect = NewClientRect; RECT NRect = NewClientRect;
@ -865,43 +925,40 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
} }
/* No use in copying bits which are in the update region. */ /* No use in copying bits which are in the update region. */
if ((HRGN) 1 == Window->UpdateRegion) if (Window->UpdateRegion != NULL)
{
/* The whole window is in the update region. No use
copying anything, so set the copy region empty */
NtGdiSetRectRgn(CopyRgn, 0, 0, 0, 0);
}
else if (1 < (DWORD) Window->UpdateRegion)
{ {
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF); NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
} }
/*
/* Now, get the bounding box of the copy region. If it's empty * Now, get the bounding box of the copy region. If it's empty
there's nothing to copy. Also, it's no use copying bits onto * there's nothing to copy. Also, it's no use copying bits onto
themselves */ * themselves.
UnsafeIntGetRgnBox(CopyRgn, &CopyRect); */
if (NtGdiIsEmptyRect(&CopyRect)) if (UnsafeIntGetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
{ {
/* Nothing to copy, clean up */ /* Nothing to copy, clean up */
NtGdiDeleteObject(CopyRgn); NtGdiDeleteObject(CopyRgn);
CopyRgn = NULL; CopyRgn = NULL;
} }
else if (OldWindowRect.left != NewWindowRect.left else if (OldWindowRect.left != NewWindowRect.left ||
|| OldWindowRect.top != NewWindowRect.top) OldWindowRect.top != NewWindowRect.top)
{ {
/* Small trick here: there is no function to bitblt a region. So /*
we set the region as the clipping region, take the bounding box * Small trick here: there is no function to bitblt a region. So
of the region and bitblt that. Since nothing outside the clipping * we set the region as the clipping region, take the bounding box
region is copied, this has the effect of bitblt'ing the region. * of the region and bitblt that. Since nothing outside the clipping
* region is copied, this has the effect of bitblt'ing the region.
Since NtUserGetDCEx takes ownership of the clip region, we need *
to create a copy of CopyRgn and pass that. We need CopyRgn later */ * Since NtUserGetDCEx takes ownership of the clip region, we need
* to create a copy of CopyRgn and pass that. We need CopyRgn later
*/
HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY); NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY);
Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE | Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE |
DCX_INTERSECTRGN | DCX_CLIPSIBLINGS); DCX_INTERSECTRGN | DCX_CLIPSIBLINGS);
NtGdiBitBlt(Dc, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left, NtGdiBitBlt(Dc,
CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
CopyRect.bottom - CopyRect.top, Dc, CopyRect.bottom - CopyRect.top, Dc,
CopyRect.left + (OldWindowRect.left - NewWindowRect.left), CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY); CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
@ -914,81 +971,63 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
} }
/* We need to redraw what wasn't visible before */ /* We need to redraw what wasn't visible before */
if (NULL != VisAfter) if (VisAfter != NULL)
{ {
if (NULL != CopyRgn) if (CopyRgn != NULL)
{ {
DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0); DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
if (ERROR != RgnType && NULLREGION != RgnType) if (RgnType != ERROR && RgnType != NULLREGION)
{ {
NtGdiOffsetRgn(DirtyRgn, NtGdiOffsetRgn(DirtyRgn,
Window->WindowRect.left - Window->ClientRect.left, Window->WindowRect.left - Window->ClientRect.left,
Window->WindowRect.top - Window->ClientRect.top); Window->WindowRect.top - Window->ClientRect.top);
IntRedrawWindow(Window, NULL, DirtyRgn, IntRedrawWindow(Window, NULL, DirtyRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
RDW_ALLCHILDREN |
((flags & SWP_NOREDRAW) ? 0 : RDW_ERASENOW | RDW_UPDATENOW));
} }
NtGdiDeleteObject(DirtyRgn); NtGdiDeleteObject(DirtyRgn);
} }
else else
{ {
IntRedrawWindow(Window, NULL, NULL, IntRedrawWindow(Window, NULL, NULL,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
RDW_ALLCHILDREN |
((flags & SWP_NOREDRAW) ? 0 : RDW_ERASENOW | RDW_UPDATENOW));
} }
} }
if (NULL != CopyRgn) if (CopyRgn != NULL)
{ {
NtGdiDeleteObject(CopyRgn); NtGdiDeleteObject(CopyRgn);
} }
}
/* Expose what was covered before but not covered anymore */ /* Expose what was covered before but not covered anymore */
if (NULL != VisBefore) if (VisBefore != NULL)
{ {
ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0); ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left, NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
OldWindowRect.top - NewWindowRect.top); OldWindowRect.top - NewWindowRect.top);
if (NULL != VisAfter) if (VisAfter != NULL)
{
RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
}
else else
{
RgnType = SIMPLEREGION; RgnType = SIMPLEREGION;
}
if (ERROR != RgnType && NULLREGION != RgnType) if (RgnType != ERROR && RgnType != NULLREGION)
{ {
VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window,
ExposedRgn, !(flags & SWP_NOREDRAW)); ExposedRgn);
} }
NtGdiDeleteObject(ExposedRgn); NtGdiDeleteObject(ExposedRgn);
NtGdiDeleteObject(VisBefore); NtGdiDeleteObject(VisBefore);
} }
if (NULL != VisAfter) if (VisAfter != NULL)
{ {
NtGdiDeleteObject(VisAfter); NtGdiDeleteObject(VisAfter);
} }
/* FIXME: Hide or show the claret */
if (!(flags & SWP_NOACTIVATE))
{
WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
}
/* FIXME: Check some conditions before doing this. */
IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
IntReleaseWindowObject(Window); IntReleaseWindowObject(Window);
return(TRUE);
return TRUE;
} }
LRESULT STDCALL LRESULT STDCALL