From db573c519a0c3878a86ae0878b7e3ffa59d430b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Tue, 9 Sep 2003 09:39:21 +0000 Subject: [PATCH] Fixes to WinPosSetWindowPos() and the routines it depends upon svn path=/trunk/; revision=6020 --- .../drivers/dd/vga/display/objects/bitblt.c | 27 +- reactos/include/win32k/region.h | 1 + reactos/lib/user32/windows/defwnd.c | 13 +- reactos/subsys/win32k/eng/bitblt.c | 33 +- reactos/subsys/win32k/ntuser/painting.c | 95 +-- reactos/subsys/win32k/ntuser/vis.c | 143 ++++- reactos/subsys/win32k/ntuser/windc.c | 6 +- reactos/subsys/win32k/ntuser/winpos.c | 559 +++++++----------- reactos/subsys/win32k/objects/cliprgn.c | 8 +- reactos/subsys/win32k/objects/coord.c | 4 +- reactos/subsys/win32k/objects/region.c | 104 ++-- 11 files changed, 522 insertions(+), 471 deletions(-) diff --git a/reactos/drivers/dd/vga/display/objects/bitblt.c b/reactos/drivers/dd/vga/display/objects/bitblt.c index 45c767c1171..491d791c930 100644 --- a/reactos/drivers/dd/vga/display/objects/bitblt.c +++ b/reactos/drivers/dd/vga/display/objects/bitblt.c @@ -380,6 +380,8 @@ DrvBitBlt(SURFOBJ *Dest, RECT_ENUM RectEnum; BOOL EnumMore; unsigned i; + POINTL Pt; + ULONG Direction; switch (rop4) { @@ -420,13 +422,30 @@ DrvBitBlt(SURFOBJ *Dest, case DC_RECT: // Clip the blt to the clip rectangle VGADDI_IntersectRect(&CombinedRect, DestRect, &(Clip->rclBounds)); + Pt.x = SourcePoint->x + CombinedRect.left - DestRect->left; + Pt.y = SourcePoint->y + CombinedRect.top - DestRect->top; Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect, - SourcePoint, MaskPoint, Brush, BrushPoint, + &Pt, MaskPoint, Brush, BrushPoint, rop4); break; case DC_COMPLEX: Ret = TRUE; - CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT); + if (Dest == Source) + { + if (DestRect->top <= SourcePoint->y) + { + Direction = DestRect->left < SourcePoint->x ? CD_RIGHTDOWN : CD_LEFTDOWN; + } + else + { + Direction = DestRect->left < SourcePoint->x ? CD_RIGHTUP : CD_LEFTUP; + } + } + else + { + Direction = CD_ANY; + } + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, ENUM_RECT_LIMIT); do { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); @@ -434,8 +453,10 @@ DrvBitBlt(SURFOBJ *Dest, for (i = 0; i < RectEnum.c; i++) { VGADDI_IntersectRect(&CombinedRect, DestRect, RectEnum.arcl + i); + Pt.x = SourcePoint->x + CombinedRect.left - DestRect->left; + Pt.y = SourcePoint->y + CombinedRect.top - DestRect->top; Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect, - SourcePoint, MaskPoint, Brush, BrushPoint, rop4) && + &Pt, MaskPoint, Brush, BrushPoint, rop4) && Ret; } } diff --git a/reactos/include/win32k/region.h b/reactos/include/win32k/region.h index 89d1135453c..0588984b665 100644 --- a/reactos/include/win32k/region.h +++ b/reactos/include/win32k/region.h @@ -154,5 +154,6 @@ HRGN STDCALL REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpP HRGN STDCALL UnsafeIntCreateRectRgnIndirect(CONST PRECT rc); INT STDCALL UnsafeIntGetRgnBox(HRGN hRgn, LPRECT pRect); HRGN FASTCALL UnsafeIntUnionRectWithRgn(HRGN hDest, CONST PRECT Rect); +BOOL FASTCALL UnsafeIntRectInRegion(HRGN hRgn, CONST LPRECT rc); #endif diff --git a/reactos/lib/user32/windows/defwnd.c b/reactos/lib/user32/windows/defwnd.c index 9af44a28721..18e9aa9a18d 100644 --- a/reactos/lib/user32/windows/defwnd.c +++ b/reactos/lib/user32/windows/defwnd.c @@ -1,4 +1,4 @@ -/* $Id: defwnd.c,v 1.84 2003/09/08 18:50:00 weiden Exp $ +/* $Id: defwnd.c,v 1.85 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -602,11 +602,9 @@ UserDrawCaptionNC ( } -VOID -UserDrawFrameNC(HWND hWnd, RECT* rect, BOOL dlgFrame, BOOL active) +static VOID +UserDrawFrameNC(HDC hDC, RECT* rect, BOOL dlgFrame, BOOL active) { - HDC hDC = GetWindowDC(hWnd); - SelectObject( hDC, GetSysColorBrush(COLOR_WINDOW) ); DrawEdge(hDC, rect,EDGE_RAISED, BF_RECT | BF_MIDDLE); } @@ -624,7 +622,6 @@ DefWndDoPaintNC(HWND hWnd, HRGN clip) ULONG ExStyle; int wFrame = 0; - // This won't work because it conflicts with BS_BITMAP : if (GetActiveWindow() == hWnd) Active = TRUE; Style = GetWindowLongW(hWnd, GWL_STYLE); ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE); @@ -645,12 +642,12 @@ DefWndDoPaintNC(HWND hWnd, HRGN clip) SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME)); if (UserHasThickFrameStyle(Style, ExStyle)) { - UserDrawFrameNC(hWnd, &rect, FALSE, Active); + UserDrawFrameNC(hDC, &rect, FALSE, Active); wFrame = GetSystemMetrics(SM_CXSIZEFRAME); } else if (UserHasDlgFrameStyle(Style, ExStyle)) { - UserDrawFrameNC(hWnd, &rect, TRUE, Active); + UserDrawFrameNC(hDC, &rect, TRUE, Active); wFrame = GetSystemMetrics(SM_CXDLGFRAME); } if (Style & WS_CAPTION) diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c index 5668265391c..677c246f3c1 100644 --- a/reactos/subsys/win32k/eng/bitblt.c +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -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: bitblt.c,v 1.26 2003/08/17 17:32:58 royce Exp $ +/* $Id: bitblt.c,v 1.27 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -105,11 +105,11 @@ BltMask(PSURFOBJ Dest, if (Mask != NULL) { - tMask = Mask->pvBits; + tMask = Mask->pvBits + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3); for (j = 0; j < dy; j++) { lMask = tMask; - c8 = 0; + c8 = SourcePoint->x & 0x07; for (i = 0; i < dx; i++) { if (0 != (*lMask & maskbit[c8])) @@ -213,6 +213,8 @@ EngBitBlt(SURFOBJ *DestObj, BOOLEAN Ret; RECTL ClipRect; unsigned i; + POINTL Pt; + ULONG Direction; if (NULL != SourcePoint) { @@ -340,12 +342,29 @@ EngBitBlt(SURFOBJ *DestObj, ClipRect.top = ClipRegion->rclBounds.top + Translate.y; ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect); + Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left; + Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top; Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation, - &CombinedRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4); + &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4); break; case DC_COMPLEX: Ret = TRUE; - CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT); + if (OutputObj == InputObj) + { + if (OutputRect.top < InputPoint.y) + { + Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN; + } + else + { + Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP; + } + } + else + { + Direction = CD_ANY; + } + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, ENUM_RECT_LIMIT); do { EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); @@ -357,8 +376,10 @@ EngBitBlt(SURFOBJ *DestObj, ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect); + Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left; + Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top; Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation, - &CombinedRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4) && + &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4) && Ret; } } diff --git a/reactos/subsys/win32k/ntuser/painting.c b/reactos/subsys/win32k/ntuser/painting.c index f37262e1609..0c74f5201d0 100644 --- a/reactos/subsys/win32k/ntuser/painting.c +++ b/reactos/subsys/win32k/ntuser/painting.c @@ -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.30 2003/08/28 13:38:24 gvg Exp $ +/* $Id: painting.c,v 1.31 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -274,7 +274,8 @@ PaintUpdateRgns(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags, } Window->UpdateRegion = REGION_CropRgn(Window->UpdateRegion, - Window->UpdateRegion, &Rect, NULL); + Window->UpdateRegion ? Window->UpdateRegion : hRgn, + &Rect, NULL); if (! HadOne) { UnsafeIntGetRgnBox(Window->UpdateRegion, &Rect); @@ -389,42 +390,38 @@ PaintUpdateRgns(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags, { POINT Total = {0, 0}; POINT PrevOrign = {0, 0}; - POINT Client; PWINDOW_OBJECT Child; - Client.x = Window->ClientRect.left - Window->WindowRect.left; - Client.y = Window->ClientRect.top - Window->WindowRect.top; + ExAcquireFastMutexUnsafe(&Window->ChildrenListLock); + Child = Window->FirstChild; + while (Child) + { + if (0 != (Child->Style & WS_VISIBLE)) + { + POINT Offset; - ExAcquireFastMutexUnsafe(&Window->ChildrenListLock); - Child = Window->FirstChild; - while (Child) - { - if (0 != (Child->Style & WS_VISIBLE)) - { - POINT Offset; + Rect.left = Child->WindowRect.left - Window->WindowRect.left; + Rect.top = Child->WindowRect.top - Window->WindowRect.top; + Rect.right = Child->WindowRect.right - Window->WindowRect.left; + Rect.bottom = Child->WindowRect.bottom - Window->WindowRect.top; - 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; + NtGdiOffsetRect(&Rect, -Total.x, -Total.y); - Offset.x = Rect.left - PrevOrign.x; - Offset.y = Rect.top - PrevOrign.y; - NtGdiOffsetRect(&Rect, -Total.x, -Total.y); - - if (NtGdiRectInRegion(hRgn, &Rect)) - { - NtGdiOffsetRgn(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; - } - } - Child = Child->NextSibling; - } - ExReleaseFastMutexUnsafe(&Window->ChildrenListLock); + if (UnsafeIntRectInRegion(hRgn, &Rect)) + { + NtGdiOffsetRgn(hRgn, -Offset.x, -Offset.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; + } + } + Child = Child->NextSibling; + } + ExReleaseFastMutexUnsafe(&Window->ChildrenListLock); NtGdiOffsetRgn(hRgn, Total.x, Total.y); HasChildren = FALSE; @@ -746,11 +743,11 @@ PaintUpdateNCRegion(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags) UnsafeIntGetRgnBox(Window->UpdateRegion, &UpdateRegionBox); NtGdiUnionRect(&Rect, &ClientRect, &UpdateRegionBox); if (Rect.left != ClientRect.left || Rect.top != ClientRect.top || - Rect.right != ClientRect.right || Rect.right != ClientRect.right) + Rect.right != ClientRect.right || Rect.bottom != ClientRect.bottom) { hClip = Window->UpdateRegion; Window->UpdateRegion = REGION_CropRgn(hRgn, hClip, - &Rect, NULL); + &ClientRect, NULL); if (Flags & UNC_REGION) { hRgnRet = hClip; @@ -854,6 +851,28 @@ NtUserEndPaint(HWND hWnd, CONST PAINTSTRUCT* lPs) return(TRUE); } +static +HRGN FASTCALL +GetClientUpdateRegion(PWINDOW_OBJECT Window) +{ + POINT Offset; + RECT Rect; + + if ((DWORD) Window->UpdateRegion <= 1) + { + return Window->UpdateRegion; + } + + Offset.x = Window->WindowRect.left - Window->ClientRect.left; + Offset.y = Window->WindowRect.top - Window->ClientRect.top; + Rect.left = - Offset.x; + Rect.top = - Offset.y; + Rect.right = Rect.left + (Window->ClientRect.right - Window->ClientRect.left); + Rect.bottom = Rect.top + (Window->ClientRect.bottom - Window->ClientRect.top); + + return REGION_CropRgn(NULL, Window->UpdateRegion, &Rect, &Offset); +} + HDC STDCALL NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs) { @@ -881,7 +900,11 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs) } /* retrieve update region */ - UpdateRegion = Window->UpdateRegion; + UpdateRegion = GetClientUpdateRegion(Window); + if (1 < (DWORD) Window->UpdateRegion) + { + NtGdiDeleteObject(Window->UpdateRegion); + } Window->UpdateRegion = 0; if (UpdateRegion != NULL || (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) { diff --git a/reactos/subsys/win32k/ntuser/vis.c b/reactos/subsys/win32k/ntuser/vis.c index b280130c729..4ed2b13d474 100644 --- a/reactos/subsys/win32k/ntuser/vis.c +++ b/reactos/subsys/win32k/ntuser/vis.c @@ -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.6 2003/08/19 11:48:50 weiden Exp $ + * $Id: vis.c,v 1.7 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -139,6 +139,7 @@ VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window, RECT Rect; HRGN ClipRgn; PWINDOW_OBJECT DesktopWindow; + INT LeftOffset, TopOffset; DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow); if (NULL == DesktopWindow) @@ -152,6 +153,17 @@ VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window, VisRgn = UnsafeIntCreateRectRgnIndirect(&Rect); if (NULL != VisRgn) { + if (ClientArea) + { + LeftOffset = Window->ClientRect.left; + TopOffset = Window->ClientRect.top; + } + else + { + LeftOffset = Window->WindowRect.left; + TopOffset = Window->WindowRect.top; + } + ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); if (ClipRgn != NULL) @@ -179,6 +191,7 @@ VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window, NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); NtGdiDeleteObject(ClipRgn); + NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset); } else { @@ -208,6 +221,34 @@ VIS_RepaintDesktop(HWND Desktop, HRGN RepaintRgn) NtUserReleaseDC(Desktop, dc); } + +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 @@ -215,33 +256,95 @@ VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window, HRGN NewlyExposed) { PWINDOW_OBJECT DesktopWindow; - PWINDOW_OBJECT Child; + PWINDOW_OBJECT Parent; + PWINDOW_OBJECT Sibling; + PWINDOW_OBJECT TopLevel; HRGN Uncovered; - HRGN Covered; HRGN Repaint; + HRGN DirtyRgn; + HRGN ExposedWindow; + HRGN Covered; + INT RgnType; + POINT Offset; DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow); Uncovered = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect); - ExAcquireFastMutexUnsafe(&DesktopWindow->ChildrenListLock); - Child = DesktopWindow->FirstChild; - while (Child) - { - if (0 != (Child->Style & WS_VISIBLE)) + if (Window->Style & WS_CHILD) { - Covered = UnsafeIntCreateRectRgnIndirect(&Child->WindowRect); - NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF); - PaintRedrawWindow(Child, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE, 0); - NtGdiDeleteObject(Covered); - } - Child = Child->NextSibling; - } - ExReleaseFastMutexUnsafe(&DesktopWindow->ChildrenListLock); + /* Determine our toplevel window */ + TopLevel = Window; + while (TopLevel->Style & WS_CHILD) + { + TopLevel = TopLevel->Parent; + } - Repaint = NtGdiCreateRectRgn(0, 0, 0, 0); - NtGdiCombineRgn(Repaint, NewlyExposed, Uncovered, RGN_AND); - VIS_RepaintDesktop(DesktopWindow->Self, Repaint); - NtGdiDeleteObject(Repaint); + 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) + { + PaintRedrawWindow(Sibling, NULL, DirtyRgn, + RDW_INVALIDATE | RDW_FRAME | RDW_ERASE + | RDW_ALLCHILDREN, RDW_EX_XYWINDOW); + } + 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) + { + PaintRedrawWindow(Parent, NULL, DirtyRgn, + RDW_INVALIDATE | RDW_FRAME | RDW_ERASE + | RDW_NOCHILDREN, RDW_EX_XYWINDOW); + } + 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); + VIS_RepaintDesktop(DesktopWindow->Self, Repaint); + NtGdiDeleteObject(Repaint); + } NtGdiDeleteObject(Uncovered); } diff --git a/reactos/subsys/win32k/ntuser/windc.c b/reactos/subsys/win32k/ntuser/windc.c index b5c3109d0ca..239294769b6 100644 --- a/reactos/subsys/win32k/ntuser/windc.c +++ b/reactos/subsys/win32k/ntuser/windc.c @@ -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.22 2003/08/20 07:45:01 gvg Exp $ +/* $Id: windc.c,v 1.23 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -416,12 +416,12 @@ NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags) } } - if (0 != (Dce->DCXFlags & DCX_INTERSECTRGN)) + if (0 != (Flags & DCX_INTERSECTRGN)) { NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND); } - if (0 != (Dce->DCXFlags & DCX_EXCLUDERGN)) + if (0 != (Flags & DCX_EXCLUDERGN)) { NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF); } diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index 01a738272a0..3c7a2423420 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -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.29 2003/08/29 09:29:11 gvg Exp $ +/* $Id: winpos.c,v 1.30 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -378,7 +378,66 @@ LONG STATIC STDCALL WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos, RECT* WindowRect, RECT* ClientRect) { - return 0; /* FIXME: Calculate non client size */ + UINT wvrFlags = 0; + + /* Send WM_NCCALCSIZE message to get new client area */ + if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE) + { + NCCALCSIZE_PARAMS params; + WINDOWPOS winposCopy; + + params.rgrc[0] = *WindowRect; + params.rgrc[1] = Window->WindowRect; + params.rgrc[2] = Window->ClientRect; + if (Window->Style & WS_CHILD) + { + NtGdiOffsetRect(&(params.rgrc[2]), - Window->Parent->ClientRect.left, + - Window->Parent->ClientRect.top); + } + params.lppos = &winposCopy; + winposCopy = *WinPos; + + wvrFlags = IntSendNCCALCSIZEMessage(Window->Self, TRUE, NULL, ¶ms); + + /* If the application send back garbage, ignore it */ + if (params.rgrc[0].left <= params.rgrc[0].right && + params.rgrc[0].top <= params.rgrc[0].bottom) + { + *ClientRect = params.rgrc[0]; + if (Window->Style & WS_CHILD) + { + NtGdiOffsetRect(ClientRect, Window->Parent->ClientRect.left, + Window->Parent->ClientRect.top); + } + } + + /* FIXME: WVR_ALIGNxxx */ + + if (ClientRect->left != Window->ClientRect.left || + ClientRect->top != Window->ClientRect.top) + { + WinPos->flags &= ~SWP_NOCLIENTMOVE; + } + + if ((ClientRect->right - ClientRect->left != + Window->ClientRect.right - Window->ClientRect.left) || + (ClientRect->bottom - ClientRect->top != + Window->ClientRect.bottom - Window->ClientRect.top)) + { + WinPos->flags &= ~SWP_NOCLIENTSIZE; + } + } + else + { + if (! (WinPos->flags & SWP_NOMOVE) + && (ClientRect->left != Window->ClientRect.left || + ClientRect->top != Window->ClientRect.top)) + { + WinPos->flags &= ~SWP_NOCLIENTMOVE; + } + } + + return wvrFlags; } BOOL STDCALL @@ -416,280 +475,9 @@ WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject, WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; - if (!(WinPos->flags & SWP_NOSIZE) || !(WinPos->flags & SWP_NOMOVE)) - { - WinPosGetNonClientSize(WindowObject->Self, WindowRect, ClientRect); - } - return(TRUE); } -/*********************************************************************** - * SWP_DoSimpleFrameChanged - * - * NOTE: old and new client rect origins are identical, only - * extents may have changed. Window extents are the same. - */ -VOID STATIC -WinPosDoSimpleFrameChanged( PWINDOW_OBJECT wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags ) -{ - INT i = 0; - RECT rect; - HRGN hrgn = 0; - - if( !(swpFlags & SWP_NOCLIENTSIZE) ) - { - /* Client rect changed its position/size, most likely a scrollar - * was added/removed. - * - * FIXME: WVR alignment flags - */ - - if( wndPtr->ClientRect.right > pOldClientRect->right ) /* right edge */ - { - i++; - rect.top = 0; - rect.bottom = wndPtr->ClientRect.bottom - wndPtr->ClientRect.top; - rect.right = wndPtr->ClientRect.right - wndPtr->ClientRect.left; - if(!(uFlags & SWP_EX_NOCOPY)) - rect.left = pOldClientRect->right - wndPtr->ClientRect.left; - else - { - rect.left = 0; - goto redraw; - } - } - - if( wndPtr->ClientRect.bottom > pOldClientRect->bottom ) /* bottom edge */ - { - if( i ) - hrgn = NtGdiCreateRectRgnIndirect( &rect ); - rect.left = 0; - rect.right = wndPtr->ClientRect.right - wndPtr->ClientRect.left; - rect.bottom = wndPtr->ClientRect.bottom - wndPtr->ClientRect.top; - if(!(uFlags & SWP_EX_NOCOPY)) - rect.top = pOldClientRect->bottom - wndPtr->ClientRect.top; - else - rect.top = 0; - if( i++ ) - { - HRGN hRectRgn = NtGdiCreateRectRgnIndirect(&rect); - NtGdiCombineRgn(hrgn, hrgn, hRectRgn, RGN_OR); - NtGdiDeleteObject(hRectRgn); - } - } - - if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */ - { - rect = wndPtr->WindowRect; - NtGdiOffsetRect( &rect, wndPtr->WindowRect.left - wndPtr->ClientRect.left, - wndPtr->WindowRect.top - wndPtr->ClientRect.top ); - i++; - } - } - - if( i ) - { -redraw: - PaintRedrawWindow( wndPtr, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | - RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN ); - } - else - { - PaintUpdateNCRegion(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE); - } - - if( hrgn > (HRGN)1 ) - NtGdiDeleteObject( hrgn ); -} - -/*********************************************************************** - * SWP_CopyValidBits - * - * Make window look nice without excessive repainting - * - * visible and update regions are in window coordinates - * client and window rectangles are in parent client coordinates - * - * Returns: uFlags and a dirty region in *pVisRgn. - */ -static UINT WinPosCopyValidBits( PWINDOW_OBJECT Wnd, HRGN* pVisRgn, - LPRECT lpOldWndRect, - LPRECT lpOldClientRect, UINT uFlags ) -{ - RECT r; - HRGN newVisRgn, dirtyRgn; - INT my = COMPLEXREGION; - - if( Wnd->UpdateRegion == (HRGN)1 ) - uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */ - - newVisRgn = DceGetVisRgn( Wnd->Self, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0); - NtGdiOffsetRgn(newVisRgn, -Wnd->WindowRect.left, -Wnd->WindowRect.top); - dirtyRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - - if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */ - my = NtGdiCombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND ); - - if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) ) - { -nocopy: - - /* set dirtyRgn to the sum of old and new visible regions - * in parent client coordinates */ - - NtGdiOffsetRgn( newVisRgn, Wnd->WindowRect.left, Wnd->WindowRect.top ); - NtGdiOffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top ); - - NtGdiCombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR ); - } - else /* copy valid bits to a new location */ - { - INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch; - HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */ - - /* subtract already invalid region inside Wnd from the dst region */ - - if( Wnd->UpdateRegion ) - if( NtGdiCombineRgn( hrgnValid, hrgnValid, Wnd->UpdateRegion, RGN_DIFF) == NULLREGION ) - goto nocopy; - - /* check if entire window can be copied */ - - ow = lpOldWndRect->right - lpOldWndRect->left; - oh = lpOldWndRect->bottom - lpOldWndRect->top; - nw = Wnd->WindowRect.right - Wnd->WindowRect.left; - nh = Wnd->WindowRect.bottom - Wnd->WindowRect.top; - - ocw = lpOldClientRect->right - lpOldClientRect->left; - och = lpOldClientRect->bottom - lpOldClientRect->top; - ncw = Wnd->ClientRect.right - Wnd->ClientRect.left; - nch = Wnd->ClientRect.bottom - Wnd->ClientRect.top; - - if( (ocw != ncw) || (och != nch) || - ( ow != nw) || ( oh != nh) || - ((lpOldClientRect->top - lpOldWndRect->top) != - (Wnd->ClientRect.top - Wnd->WindowRect.top)) || - ((lpOldClientRect->left - lpOldWndRect->left) != - (Wnd->ClientRect.left - Wnd->WindowRect.left)) ) - { - if(uFlags & SWP_EX_PAINTSELF) - { - /* movement relative to the window itself */ - dx = (Wnd->ClientRect.left - Wnd->WindowRect.left) - - (lpOldClientRect->left - lpOldWndRect->left) ; - dy = (Wnd->ClientRect.top - Wnd->WindowRect.top) - - (lpOldClientRect->top - lpOldWndRect->top) ; - } - else - { - /* movement relative to the parent's client area */ - dx = Wnd->ClientRect.left - lpOldClientRect->left; - dy = Wnd->ClientRect.top - lpOldClientRect->top; - } - - /* restrict valid bits to the common client rect */ - - r.left = Wnd->ClientRect.left - Wnd->WindowRect.left; - r.top = Wnd->ClientRect.top - Wnd->WindowRect.top; - r.right = r.left + min( ocw, ncw ); - r.bottom = r.top + min( och, nch ); - - REGION_CropRgn( hrgnValid, hrgnValid, &r, - (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->WindowRect)); - NtGdiGetRgnBox( hrgnValid, &r ); - if( NtGdiIsEmptyRect( &r ) ) - goto nocopy; - r = *lpOldClientRect; - } - else - { - if(uFlags & SWP_EX_PAINTSELF) { - /* - * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move - * relative to itself, only the client area can change. - * if the client rect didn't change, there's nothing to do. - */ - dx = 0; - dy = 0; - } - else - { - dx = Wnd->WindowRect.left - lpOldWndRect->left; - dy = Wnd->WindowRect.top - lpOldWndRect->top; - NtGdiOffsetRgn( hrgnValid, Wnd->WindowRect.left, Wnd->WindowRect.top ); - } - r = *lpOldWndRect; - } - - if( !(uFlags & SWP_EX_PAINTSELF) ) - { - /* Move remaining regions to parent coordinates */ - NtGdiOffsetRgn( newVisRgn, Wnd->WindowRect.left, Wnd->WindowRect.top ); - NtGdiOffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top ); - } - else - NtGdiOffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top ); - - /* Compute combined dirty region (old + new - valid) */ - NtGdiCombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR); - NtGdiCombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF); - - /* Blt valid bits, r is the rect to copy */ - - if( dx || dy ) - { - RECT rClip; - HDC hDC; - - /* get DC and clip rect with drawable rect to avoid superfluous expose events - from copying clipped areas */ - - if( uFlags & SWP_EX_PAINTSELF ) - { - hDC = NtUserGetDCEx( Wnd->Self, hrgnValid, DCX_WINDOW | DCX_CACHE | - DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ); - rClip.right = nw; rClip.bottom = nh; - } - else - { - hDC = NtUserGetDCEx( Wnd->Parent->Self, hrgnValid, DCX_CACHE | - DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ); - rClip.right = Wnd->Parent->ClientRect.right - Wnd->Parent->ClientRect.left; - rClip.bottom = Wnd->Parent->ClientRect.bottom - Wnd->Parent->ClientRect.top; - } - rClip.left = rClip.top = 0; - - if( oh > nh ) r.bottom = r.top + nh; - if( ow < nw ) r.right = r.left + nw; - - if( NtGdiIntersectRect( &r, &r, &rClip ) ) - { - NtGdiBitBlt(hDC, dx + r.left, dy + r.top, r.right - r.left, r.bottom - r.top, hDC, r.left, r.top, SRCCOPY); - - /* When you copy the bits without repainting, parent doesn't - get validated appropriately. Therefore, we have to validate - the parent with the windows' updated region when the - parent's update region is not empty. */ - - if (Wnd->Parent->UpdateRegion != 0 && !(Wnd->Parent->Style & WS_CLIPCHILDREN)) - { - NtGdiOffsetRect(&r, dx, dy); - NtUserValidateRect(Wnd->Parent->Self, &r); - } - } - NtUserReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? - Wnd->Self : Wnd->Parent->Self, hDC); - } - } - - /* *pVisRgn now points to the invalidated region */ - - NtGdiDeleteObject(newVisRgn); - NtGdiDeleteObject(dirtyRgn); - return uFlags; -} - /*********************************************************************** * WinPosInternalMoveWindow * @@ -731,11 +519,18 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, WINDOWPOS WinPos; RECT NewWindowRect; RECT NewClientRect; - HRGN VisRgn = NULL; - HRGN VisibleRgn = NULL; + HRGN VisBefore = NULL; + HRGN VisAfter = NULL; + HRGN DirtyRgn = NULL; + HRGN ExposedRgn = NULL; + HRGN CopyRgn = NULL; ULONG WvrFlags = 0; RECT OldWindowRect, OldClientRect; UINT FlagsEx = 0; + int RgnType; + HDC Dc; + RECT CopyRect; + RECT TempRect; /* FIXME: Get current active window from active queue. */ @@ -822,6 +617,7 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, /* FIXME: Adjust flags based on WndInsertAfter */ + /* Compute the visible region before the window position is changed */ if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) && WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != @@ -829,15 +625,19 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, { if (Window->Style & WS_CLIPCHILDREN) { - VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, - Window, FALSE, FALSE, TRUE); + VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, + Window, FALSE, FALSE, TRUE); } else { - VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, - Window, FALSE, FALSE, FALSE); + VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, + Window, FALSE, FALSE, FALSE); + } + if (NULLREGION == UnsafeIntGetRgnBox(VisBefore, &TempRect)) + { + NtGdiDeleteObject(VisBefore); + VisBefore = NULL; } - NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top); } WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, @@ -865,96 +665,167 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, { Window->Style |= WS_VISIBLE; FlagsEx |= SWP_EX_PAINTSELF; - /* Redraw entire window. */ - VisRgn = (HRGN) 1; } - else if (!(WinPos.flags & SWP_NOREDRAW)) + else if (WinPos.flags & SWP_HIDEWINDOW) { - if (WinPos.flags & SWP_HIDEWINDOW) + Window->Style &= ~WS_VISIBLE; + } + + if (!(WinPos.flags & SWP_NOREDRAW)) + { + /* Determine the new visible region */ + if (Window->Style & WS_CLIPCHILDREN) { - if (VisRgn > (HRGN)1) + VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, + Window, FALSE, FALSE, TRUE); + } + else + { + VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, + Window, FALSE, FALSE, FALSE); + } + if (NULLREGION == UnsafeIntGetRgnBox(VisAfter, &TempRect)) + { + NtGdiDeleteObject(VisAfter); + 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 + position. */ + if (NULL != VisBefore && NULL != VisAfter && ! (WinPos.flags & SWP_NOCOPYBITS)) + { + CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0); + 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, + 'cause there is no use in copying it (would possibly cause + "flashing" too). However, if the copy region is already empty, + we don't have to crop (can't take anything away from an empty + region...) */ + if (! (WinPos.flags & SWP_NOSIZE) + && ERROR != RgnType && NULLREGION != RgnType) { - NtGdiOffsetRgn(VisRgn, OldWindowRect.left, OldWindowRect.top); + RECT ORect = OldClientRect; + RECT NRect = NewClientRect; + NtGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top); + NtGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top); + NtGdiIntersectRect(&CopyRect, &ORect, &NRect); + REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL); } - else + + /* No use in copying bits which are in the update region. */ + if ((HRGN) 1 == Window->UpdateRegion) { - VisRgn = 0; + /* 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); + } + + + /* 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 + themselves */ + UnsafeIntGetRgnBox(CopyRgn, &CopyRect); + if (NtGdiIsEmptyRect(&CopyRect)) + { + /* Nothing to copy, clean up */ + NtGdiDeleteObject(CopyRgn); + CopyRgn = NULL; + } + else if (OldWindowRect.left != NewWindowRect.left + || 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 + 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 */ + HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); + NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY); + Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE | + DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ); + NtGdiBitBlt(Dc, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left, + CopyRect.bottom - CopyRect.top, Dc, + CopyRect.left + (OldWindowRect.left - NewWindowRect.left), + CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY); + NtUserReleaseDC(Wnd, Dc); } } else { - if ((WinPos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) + CopyRgn = NULL; + } + + /* We need to redraw what wasn't visible before */ + if (NULL != VisAfter) + { + if (NULL != CopyRgn) { - if ((WinPos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE) + DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0); + RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); + if (ERROR != RgnType && NULLREGION != RgnType) { - FlagsEx |= SWP_EX_PAINTSELF; + PaintRedrawWindow(Window, NULL, DirtyRgn, + RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | + RDW_ALLCHILDREN | RDW_ERASENOW, + RDW_EX_XYWINDOW | RDW_EX_USEHRGN); } - FlagsEx = WinPosCopyValidBits(Window, &VisRgn, &OldWindowRect, &OldClientRect, FlagsEx); + NtGdiDeleteObject(DirtyRgn); } else { - if (WinPos.flags & SWP_FRAMECHANGED) - { - WinPosDoSimpleFrameChanged(Window, &OldClientRect, WinPos.flags, FlagsEx); - } - if (VisRgn != 0) - { - NtGdiDeleteObject(VisRgn); - VisRgn = 0; - } + PaintRedrawWindow(Window, NULL, NULL, + RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | + RDW_ALLCHILDREN | RDW_ERASENOW, + RDW_EX_XYWINDOW | RDW_EX_USEHRGN); } } - } - if (WinPos.flags & SWP_HIDEWINDOW) - { - VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window, - FALSE, FALSE, FALSE); - Window->Style &= ~WS_VISIBLE; - VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn); - NtGdiDeleteObject(VisibleRgn); + if (NULL != CopyRgn) + { + NtGdiDeleteObject(CopyRgn); + } } - if (! (WinPos.flags & SWP_NOMOVE)) + /* Expose what was covered before but not covered anymore */ + if (NULL != VisBefore) { - VisibleRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); - NtGdiCombineRgn(VisibleRgn, VisRgn, VisibleRgn, RGN_DIFF); - VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn); - NtGdiDeleteObject(VisibleRgn); + ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0); + NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); + NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left, + OldWindowRect.top - NewWindowRect.top); + if (NULL != VisAfter) + { + RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); + } + else + { + RgnType = SIMPLEREGION; + } + if (ERROR != RgnType && NULLREGION != RgnType) + { + VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, ExposedRgn); + } + NtGdiDeleteObject(ExposedRgn); + + NtGdiDeleteObject(VisBefore); + } + + if (NULL != VisAfter) + { + NtGdiDeleteObject(VisAfter); } /* FIXME: Hide or show the claret */ - if (VisRgn) - { - if (!(WinPos.flags & SWP_NOREDRAW)) - { - if (FlagsEx & SWP_EX_PAINTSELF) - { - PaintRedrawWindow(Window, NULL, - (VisRgn == (HRGN) 1) ? 0 : VisRgn, - RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | - RDW_ALLCHILDREN | RDW_ERASENOW, - RDW_EX_XYWINDOW | RDW_EX_USEHRGN); - } -#if 0 - else - { - PaintRedrawWindow(Window->Parent, NULL, - (VisRgn == (HRGN) 1) ? 0 : VisRgn, - RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN | - RDW_ERASENOW, - RDW_EX_USEHRGN); - } -#endif - /* FIXME: Redraw the window parent. */ - } - if ((HRGN) 1 != VisRgn) - { - NtGdiDeleteObject(VisRgn); - } - } - if (!(flags & SWP_NOACTIVATE)) { WinPosChangeActiveWindow(WinPos.hwnd, FALSE); diff --git a/reactos/subsys/win32k/objects/cliprgn.c b/reactos/subsys/win32k/objects/cliprgn.c index bda5634b562..37537fb26b1 100644 --- a/reactos/subsys/win32k/objects/cliprgn.c +++ b/reactos/subsys/win32k/objects/cliprgn.c @@ -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: cliprgn.c,v 1.23 2003/08/31 07:56:24 gvg Exp $ */ +/* $Id: cliprgn.c,v 1.24 2003/09/09 09:39:21 gvg Exp $ */ #undef WIN32_LEAN_AND_MEAN #include @@ -69,6 +69,7 @@ CLIPPING_UpdateGCRegion(DC* Dc) NtGdiCombineRgn(Combined, Dc->w.hClipRgn, Dc->w.hVisRgn, RGN_AND); } + NtGdiOffsetRgn(Combined, Dc->w.DCOrgX, Dc->w.DCOrgY); CombinedRegion = RGNDATA_LockRgn(Combined); ASSERT(NULL != CombinedRegion); @@ -161,10 +162,6 @@ int STDCALL NtGdiGetClipBox(HDC hDC, if (!(dc = DC_LockDc(hDC))) return ERROR; retval = UnsafeIntGetRgnBox(dc->w.hGCClipRgn, rc); - rc->left -= dc->w.DCOrgX; - rc->right -= dc->w.DCOrgX; - rc->top -= dc->w.DCOrgY; - rc->bottom -= dc->w.DCOrgY; DC_UnlockDc( hDC ); NtGdiDPtoLP(hDC, (LPPOINT)rc, 2); @@ -241,7 +238,6 @@ int STDCALL NtGdiSelectClipRgn(HDC hDC, DC_UnlockDc(hDC); return ERROR; } - NtGdiOffsetRgn(Copy, dc->w.DCOrgX, dc->w.DCOrgY); } else { diff --git a/reactos/subsys/win32k/objects/coord.c b/reactos/subsys/win32k/objects/coord.c index d5e7ae68b64..e69c62d98d3 100644 --- a/reactos/subsys/win32k/objects/coord.c +++ b/reactos/subsys/win32k/objects/coord.c @@ -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: coord.c,v 1.18 2003/08/20 22:07:36 royce Exp $ +/* $Id: coord.c,v 1.19 2003/09/09 09:39:21 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -229,7 +229,7 @@ NtGdiLPtoDP ( HDC hDC, LPPOINT UnsafePoints, INT Count ) MmCopyFromCaller( Points, UnsafePoints, Count*sizeof(POINT) ); - IntLPtoDP ( dc, UnsafePoints, Count ); + IntLPtoDP ( dc, Points, Count ); MmCopyToCaller ( UnsafePoints, Points, Count*sizeof(POINT) ); diff --git a/reactos/subsys/win32k/objects/region.c b/reactos/subsys/win32k/objects/region.c index b8313a5124a..7f348592ba1 100644 --- a/reactos/subsys/win32k/objects/region.c +++ b/reactos/subsys/win32k/objects/region.c @@ -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: region.c,v 1.35 2003/08/20 07:45:02 gvg Exp $ */ +/* $Id: region.c,v 1.36 2003/09/09 09:39:21 gvg Exp $ */ #undef WIN32_LEAN_AND_MEAN #include #include @@ -139,6 +139,7 @@ static void FASTCALL REGION_SetExtents (ROSRGNDATA *pReg) pReg->rdh.rcBound.top = 0; pReg->rdh.rcBound.right = 0; pReg->rdh.rcBound.bottom = 0; + pReg->rdh.iType = NULLREGION; return; } @@ -166,6 +167,7 @@ static void FASTCALL REGION_SetExtents (ROSRGNDATA *pReg) pExtents->right = pRect->right; pRect++; } + pReg->rdh.iType = (1 == pReg->rdh.nCount ? SIMPLEREGION : COMPLEXREGION); } @@ -1573,34 +1575,44 @@ NtGdiCreatePolyPolygonRgn(CONST PPOINT pt, HRGN STDCALL -NtGdiCreateRectRgn(INT LeftRect, - INT TopRect, - INT RightRect, - INT BottomRect) +NtGdiCreateRectRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect) { HRGN hRgn; PROSRGNDATA pRgnData; PRECT pRect; - // Allocate region data structure with space for 1 RECT - if( ( hRgn = RGNDATA_AllocRgn(1) ) ){ - if( ( pRgnData = RGNDATA_LockRgn( hRgn ) ) ){ - pRect = (PRECT)pRgnData->Buffer; - ASSERT(pRect); + if (RightRect < LeftRect || BottomRect < TopRect) + { + DPRINT1("Invalid parameters (%d, %d) - (%d, %d)\n", LeftRect, TopRect, RightRect, BottomRect); + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return NULL; + } - // Fill in the region data header - pRgnData->rdh.iType = SIMPLEREGION; - NtGdiSetRect(&(pRgnData->rdh.rcBound), LeftRect, TopRect, RightRect, BottomRect); + /* Allocate region data structure with space for 1 RECT */ + if ((hRgn = RGNDATA_AllocRgn(1))) + { + if ((pRgnData = RGNDATA_LockRgn(hRgn))) + { + pRect = (PRECT)pRgnData->Buffer; + ASSERT(pRect); - // use NtGdiCopyRect when implemented - NtGdiSetRect(pRect, LeftRect, TopRect, RightRect, BottomRect); - RGNDATA_UnlockRgn( hRgn ); + /* Fill in the region data header */ + pRgnData->rdh.iType = (LeftRect == RightRect || TopRect == BottomRect) ? NULLREGION : SIMPLEREGION; + NtGdiSetRect(&(pRgnData->rdh.rcBound), LeftRect, TopRect, RightRect, BottomRect); - return hRgn; + /* use NtGdiCopyRect when implemented */ + NtGdiSetRect(pRect, LeftRect, TopRect, RightRect, BottomRect); + RGNDATA_UnlockRgn(hRgn); + + return hRgn; } - NtGdiDeleteObject( hRgn ); - } - DPRINT("NtGdiCreateRectRgn: can't allocate region\n"); + NtGdiDeleteObject( hRgn ); + } + + DPRINT1("NtGdiCreateRectRgn: can't allocate region\n"); return NULL; } @@ -1764,25 +1776,21 @@ INT STDCALL NtGdiGetRgnBox(HRGN hRgn, LPRECT pRect) { - PROSRGNDATA rgn = RGNDATA_LockRgn(hRgn); + RECT SafeRect; DWORD ret; - if (rgn) + ret = UnsafeIntGetRgnBox(hRgn, &SafeRect); + if (ERROR == ret) { - RECT SafeRect; - SafeRect.left = rgn->rdh.rcBound.left; - SafeRect.top = rgn->rdh.rcBound.top; - SafeRect.right = rgn->rdh.rcBound.right; - SafeRect.bottom = rgn->rdh.rcBound.bottom; - ret = rgn->rdh.iType; - RGNDATA_UnlockRgn( hRgn ); - - if(!NT_SUCCESS(MmCopyToCaller(pRect, &SafeRect, sizeof(RECT)))) - return 0; - return ret; } - return 0; //if invalid region return zero + + if (!NT_SUCCESS(MmCopyToCaller(pRect, &SafeRect, sizeof(RECT)))) + { + return ERROR; + } + + return ret; } BOOL @@ -1917,20 +1925,14 @@ NtGdiPtInRegion(HRGN hRgn, } BOOL -STDCALL -NtGdiRectInRegion(HRGN hRgn, - CONST LPRECT unsaferc) +FASTCALL +UnsafeIntRectInRegion(HRGN hRgn, + CONST LPRECT rc) { PROSRGNDATA rgn; PRECT pCurRect, pRectEnd; - PRECT rc; BOOL bRet = FALSE; - if( !NT_SUCCESS( MmCopyFromCaller( rc, unsaferc, sizeof( RECT ) ) ) ){ - DPRINT("NtGdiRectInRegion: bogus rc\n"); - return ERROR; - } - if( !( rgn = RGNDATA_LockRgn(hRgn) ) ) return ERROR; @@ -1951,6 +1953,22 @@ NtGdiRectInRegion(HRGN hRgn, return bRet; } +BOOL +STDCALL +NtGdiRectInRegion(HRGN hRgn, + CONST LPRECT unsaferc) +{ + RECT rc; + + if (!NT_SUCCESS(MmCopyFromCaller(&rc, unsaferc, sizeof(RECT)))) + { + DPRINT1("NtGdiRectInRegion: bogus rc\n"); + return ERROR; + } + + return UnsafeIntRectInRegion(hRgn, &rc); +} + BOOL STDCALL NtGdiSetRectRgn(HRGN hRgn,