[ros-diffs] [fireball] 47966: - 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.

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Jul 7 22:10:22 UTC 2010


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/win32k/include/dc.h?rev=47966&r1=47965&r2=47966&view=diff
==============================================================================
--- 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/win32k/swm/winman.c?rev=47966&r1=47965&r2=47966&view=diff
==============================================================================
--- 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 ||




More information about the Ros-diffs mailing list