Author: fireball Date: Wed Jul 7 22:10:22 2010 New Revision: 47966
URL: http://svn.reactos.org/svn/reactos?rev=47966&view=rev Log: - SwmCopyBits: Implement moving bits of a non-foreground window (which usually is the case, because at least a taskbar is an always-on-top window). Fixes e.g. visual glitches when moving a window over the taskbar.
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h [iso-8859-1] Wed Jul 7 22:10:22 2010 @@ -29,4 +29,7 @@ ((PDC) GDIOBJ_LockObj ((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC)) #define DC_Unlock(pDC) \ GDIOBJ_UnlockObjByPtr ((PBASEOBJECT)pDC) + +VOID APIENTRY RosGdiUpdateClipping(PDC pDC); + #endif
Modified: branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c [iso-8859-1] Wed Jul 7 22:10:22 2010 @@ -614,14 +614,108 @@
VOID NTAPI -SwmCopyBits(const RECT *WindowRect, const RECT *OldRect) -{ +SwmCopyBits(const PSWM_WINDOW SwmWin, const RECT *OldRect) +{ + RECTL rcBounds; + PDC pDC; + PLIST_ENTRY Current; + struct region *TempRegion, *ParentRegion, *WinRegion = NULL; + rectangle_t rcScreen, rcOldWindow; + PSWM_WINDOW Window; + /* Lazily create a global screen DC */ if (!SwmDc) SwmCreateScreenDc();
+ /* Set clipping to prevent touching higher-level windows */ + pDC = DC_Lock(SwmDc); + + /* Check if we have higher-level windows */ + if (SwmWin->Entry.Blink != &SwmWindows) + { + /* Create a whole screen region */ + rcScreen.left = 0; + rcScreen.top = 0; + rcScreen.right = pDC->rcVport.right; + rcScreen.bottom = pDC->rcVport.bottom; + set_region_rect(pDC->Clipping, &rcScreen); + + ParentRegion = create_empty_region(); + + /* Compile a total region clipped by parent windows */ + Current = SwmWin->Entry.Blink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + /* Skip hidden windows */ + if (Window->Hidden) + { + /* Advance to the next window */ + Current = Current->Blink; + continue; + } + DPRINT("hwnd: %x\n", Window->hwnd); + + /* Calculate window's region */ + TempRegion = create_empty_region(); + set_region_rect(TempRegion, &Window->Window); + + /* Union it with parent if it's not empty and free temp region */ + if (!is_region_empty(TempRegion)) + union_region(ParentRegion, ParentRegion, TempRegion); + free_region(TempRegion); + + /* Advance to the previous window */ + Current = Current->Blink; + } + + /* Remove parts clipped by parents from the window region */ + if (!is_region_empty(ParentRegion)) + subtract_region(pDC->Clipping, pDC->Clipping, ParentRegion); + + /* Set DC clipping */ + RosGdiUpdateClipping(pDC); + + /* Get the part which was previously hidden by parent area */ + WinRegion = create_empty_region(); + rcOldWindow.bottom = OldRect->bottom; + rcOldWindow.left = OldRect->left; + rcOldWindow.top = OldRect->top; + rcOldWindow.right = OldRect->right; + set_region_rect(WinRegion, &rcOldWindow); + + intersect_region(WinRegion, WinRegion, ParentRegion); + if (!is_region_empty(WinRegion)) + { + /* Offset it to the new position */ + offset_region(WinRegion, + SwmWin->Window.left - OldRect->left, + SwmWin->Window.top - OldRect->top); + + /* Paint it */ + SwmPaintRegion(WinRegion); + } + + free_region(WinRegion); + free_region(ParentRegion); + } + else + { + /* Simple case, use whole viewport as a clipping rect */ + RECTL_vSetRect(&rcBounds, + 0, + 0, + pDC->rcVport.right, + pDC->rcVport.bottom); + IntEngDeleteClipRegion(pDC->CombinedClip); + pDC->CombinedClip = IntEngCreateClipRegion(1, &rcBounds, &rcBounds); + } + + DC_Unlock(pDC); + /* Copy bits */ - RosGdiBitBlt(SwmDc, WindowRect->left, WindowRect->top, WindowRect->right - WindowRect->left, - WindowRect->bottom - WindowRect->top, SwmDc, OldRect->left, OldRect->top, SRCCOPY); + RosGdiBitBlt(SwmDc, SwmWin->Window.left, SwmWin->Window.top, SwmWin->Window.right - SwmWin->Window.left, + SwmWin->Window.bottom - SwmWin->Window.top, SwmDc, OldRect->left, OldRect->top, SRCCOPY); }
VOID @@ -711,12 +805,7 @@ SwmClipAllWindows();
/* Copy bitmap bits if it's a move */ - if (IsMove) - { - /* FIXME: The window MUST be foreground, otherwise bits will be - copied incorrectly */ - SwmCopyBits(WindowRect, OldRect); - } + if (IsMove) SwmCopyBits(SwmWin, OldRect);
/* Paint area changed after moving or resizing */ if (Width < OldWidth ||