[ros-diffs] [fireball] 44255: - winent.drv: Inform SWM in all cases when a window really changes its size or position. - SWM: Recalculate clipping of all windows every time a window state is changed. This is more time consuming rather than the incremental approach used earlier, however it's 100% fail proof. - The above changes provide a substantial improvement to the window clipping and drawing in arwinss, except for a few unhandled cases.

fireball at svn.reactos.org fireball at svn.reactos.org
Sat Nov 21 16:02:55 CET 2009


Author: fireball
Date: Sat Nov 21 16:02:55 2009
New Revision: 44255

URL: http://svn.reactos.org/svn/reactos?rev=44255&view=rev
Log:
- winent.drv: Inform SWM in all cases when a window really changes its size or position.
- SWM: Recalculate clipping of all windows every time a window state is changed. This is more time consuming rather than the incremental approach used earlier, however it's 100% fail proof.
- The above changes provide a substantial improvement to the window clipping and drawing in arwinss, except for a few unhandled cases.

Modified:
    branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c
    branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c

Modified: branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c
URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c?rev=44255&r1=44254&r2=44255&view=diff
==============================================================================
--- branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] (original)
+++ branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] Sat Nov 21 16:02:55 2009
@@ -535,6 +535,9 @@
 
         if (flags & DCX_CLIPCHILDREN) escape.clip_children = TRUE;
     }
+
+    //FIXME("hdc %x, hwnd %x, top %x\n win_rect %s, top_rect %s\n", hdc, hwnd, top,
+    //    wine_dbgstr_rect(win_rect), wine_dbgstr_rect(top_rect));
 
     escape.dc_rect.left         = win_rect->left - top_rect->left;
     escape.dc_rect.top          = win_rect->top - top_rect->top;
@@ -838,7 +841,7 @@
 
 LRESULT CDECL RosDrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
 {
-    UNIMPLEMENTED;
+    //UNIMPLEMENTED;
     return -1;
 }
 
@@ -864,8 +867,8 @@
 
     SwmPosChanging(hwnd, window_rect);
 
-    TRACE( "win %x pos is changing. vis rect %s, win rect %s\n",
-           hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(window_rect) );
+    //TRACE( "win %x pos is changing. vis rect %s, win rect %s\n",
+    //       hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(window_rect) );
 
     *visible_rect = *window_rect;
 }
@@ -882,8 +885,8 @@
 
     if (!data) return;
 
-    TRACE( "win %x pos changed. new vis rect %s, old whole rect %s, swp_flags %x insert_after %x\n",
-           hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect), swp_flags, insert_after );
+    //TRACE( "win %x pos changed. new vis rect %s, old whole rect %s, swp_flags %x insert_after %x\n",
+    //       hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect), swp_flags, insert_after );
 
     old_whole_rect  = data->whole_rect;
     old_client_rect = data->client_rect;
@@ -911,12 +914,13 @@
                 ;//move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect );
             else
                 SwmPosChanged(hwnd, &data->whole_rect, &old_whole_rect);
-            FIXME("change1\n");
+            //FIXME("change1\n");
         }
         else
         {
             //move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect );
-            FIXME("change2\n");
+            //FIXME("change2\n");
+            SwmPosChanged(hwnd, &data->whole_rect, &old_whole_rect);
         }
     }
 
@@ -925,10 +929,10 @@
     /* Pass show/hide information to the window manager */
     if (swp_flags & SWP_SHOWWINDOW)
     {
-        if (swp_flags & SWP_NOZORDER) FIXME("no zorder change, ignoring!\n");
-        if (swp_flags & SWP_NOACTIVATE) FIXME("no activate change, ignoring!\n");
-
-        SwmSetForeground(hwnd);
+        if (swp_flags & SWP_NOZORDER) FIXME("no zorder change for hwnd %x, ignoring!\n", hwnd);
+        //if (swp_flags & SWP_NOACTIVATE) FIXME("no activate change, ignoring!\n");
+
+        //SwmSetForeground(hwnd);
         SwmShowWindow(hwnd, TRUE);
     }
     else if (swp_flags & SWP_HIDEWINDOW)

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=44255&r1=44254&r2=44255&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] Sat Nov 21 16:02:55 2009
@@ -21,6 +21,10 @@
 void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags );
 void req_update_window_zorder( const struct update_window_zorder_request *req, struct update_window_zorder_reply *reply );
 
+PSWM_WINDOW NTAPI SwmGetTopWindow();
+VOID NTAPI SwmClipAllWindows();
+VOID NTAPI SwmDrawAllWindows();
+
 VOID NTAPI SwmDumpRegion(struct region *Region);
 VOID NTAPI SwmDumpWindows();
 VOID NTAPI SwmDebugDrawWindows();
@@ -55,7 +59,6 @@
 NTAPI
 SwmInvalidateRegion(PSWM_WINDOW Window, struct region *Region, rectangle_t *Rect)
 {
-#if 1
     struct window *Win;
     struct update_window_zorder_request req;
     struct update_window_zorder_reply reply;
@@ -68,8 +71,8 @@
     /* Calculate what areas to paint */
     UserEnterExclusive();
 
-    DPRINT1("SwmInvalidateRegion hwnd %x, region:\n", Window->hwnd);
-    SwmDumpRegion(Region);
+    DPRINT("SwmInvalidateRegion hwnd %x, region:\n", Window->hwnd);
+    //SwmDumpRegion(Region);
     Win = get_window((UINT_PTR)Window->hwnd);
     if (!Win)
     {
@@ -82,10 +85,12 @@
     /* Bring every rect in a region to front */
     for (i=0; i<Region->num_rects; i++)
     {
+#if 0
         DbgPrint("(%d,%d)-(%d,%d), and redraw coords (%d,%d)-(%d,%d); ", Region->rects[i].left, Region->rects[i].top,
             Region->rects[i].right, Region->rects[i].bottom,
             Region->rects[i].left - Window->Window.left, Region->rects[i].top - Window->Window.top,
             Region->rects[i].right - Window->Window.left, Region->rects[i].bottom - Window->Window.top);
+#endif
 
         req.rect = Region->rects[i];
         req.window = (UINT_PTR)Window->hwnd;
@@ -102,23 +107,24 @@
     UserLeave();
 
     free_region(ClientRegion);
-#endif
-}
-
-VOID
-NTAPI
-SwmMarkInvisible(struct region *Region)
+}
+
+VOID
+NTAPI
+SwmPaintRegion(struct region *Region)
 {
     PLIST_ENTRY Current;
     PSWM_WINDOW Window;
-    struct region *WindowRegion;
-    struct region *InvisibleRegion;
-
-    /* Make a copy of the invisible region */
-    InvisibleRegion = create_empty_region();
-    copy_region(InvisibleRegion, Region);
-
-    /* Traverse the list to find our window */
+    struct region *RegionToPaint;
+    struct region *Intersection;
+
+    /* Make a copy of the region */
+    RegionToPaint = create_empty_region();
+    copy_region(RegionToPaint, Region);
+
+    Intersection = create_empty_region();
+
+    /* Traverse the list of windows and paint if something intersects */
     Current = SwmWindows.Flink;
     while(Current != &SwmWindows)
     {
@@ -132,55 +138,141 @@
             continue;
         }
 
-        /* Get window's region */
-        WindowRegion = create_empty_region();
-        set_region_rect(WindowRegion, &Window->Window);
-
-        //DPRINT1("Window region ext:\n");
-        //SwmDumpRegion(WindowRegion);
-        //DPRINT1("Region to mark invisible ext:\n");
-        //SwmDumpRegion(Region);
-
-        /* Region to mark invisible for this window = Update region X Window region */
-        intersect_region(WindowRegion, WindowRegion, InvisibleRegion);
-
-        /* Check if it's empty */
-        if (!is_region_empty(WindowRegion))
+        /* Check if this window has something in common with the */
+        intersect_region(Intersection, RegionToPaint, Window->Visible);
+        if (!is_region_empty(Intersection))
         {
-            //DPRINT1("Subtracting region\n");
-            //SwmDumpRegion(WindowRegion);
-            //DPRINT1("From visible region\n");
-            //SwmDumpRegion(Window->Visible);
-
-            /* If it's not empty, subtract it from visible region */
-            subtract_region(Window->Visible, Window->Visible, WindowRegion);
-
-            /* And subtract that part from our invisible region */
-            subtract_region(InvisibleRegion, InvisibleRegion, WindowRegion);
+            /* We have a region to paint, subtract it from total update region */
+            subtract_region(RegionToPaint, RegionToPaint, Intersection);
+
+            /* Paint it */
+            SwmInvalidateRegion(Window, Intersection, NULL);
         }
 
-        free_region(WindowRegion);
-
-        /* Break if our whole invisible region is mapped to underlying windows */
-        if (is_region_empty(InvisibleRegion)) break;
+        /* If we exhausted the painting region - break out of this loop */
+        if (is_region_empty(RegionToPaint)) break;
 
         /* Advance to the next window */
         Current = Current->Flink;
     }
 
-    free_region(InvisibleRegion);
-}
-
-/* NOTE: It alters the passed region! */
-VOID
-NTAPI
-SwmMarkVisible(struct region *Region)
+    /* Free allocated regions */
+    free_region(RegionToPaint);
+    free_region(Intersection);
+}
+
+VOID
+NTAPI
+SwmRecalculateVisibility(PSWM_WINDOW CalcWindow)
 {
     PLIST_ENTRY Current;
     PSWM_WINDOW Window;
-    struct region *WindowRegion;
-
-    /* Go through every window from nearest to farthest */
+    struct region *TempRegion;
+    struct region *NewRegion, *DiffRegion, *ParentRegion;
+
+    DPRINT("Calculating visibility for %x\n", CalcWindow->hwnd);
+
+    /* Check if this window is already on top */
+    if (CalcWindow == SwmGetTopWindow())
+    {
+        /* It is, make sure it's fully visible */
+        NewRegion = create_empty_region();
+        set_region_rect(NewRegion, &CalcWindow->Window);
+
+        /* Compute the difference into the temp region */
+        DiffRegion = create_empty_region();
+        subtract_region(DiffRegion, NewRegion, CalcWindow->Visible);
+
+        /* Now get rid of the old visible region */
+        free_region(CalcWindow->Visible);
+        CalcWindow->Visible = NewRegion;
+
+        /* Show the difference, if any */
+        //if (!is_region_empty(DiffRegion))
+        //    SwmInvalidateRegion(CalcWindow, DiffRegion, NULL);
+
+        /* Free up temporary regions */
+        free_region(DiffRegion);
+
+        return;
+    }
+
+    ParentRegion = create_empty_region();
+
+    /* Create a whole window region */
+    NewRegion = create_empty_region();
+    set_region_rect(NewRegion, &CalcWindow->Window);
+
+    /* Compile a total region clipped by parent windows */
+    Current = CalcWindow->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);
+
+        /* Intersect it with the target window's region */
+        intersect_region(TempRegion, TempRegion, NewRegion);
+
+        /* 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;
+    }
+
+    DPRINT("Parent region:\n");
+    //SwmDumpRegion(ParentRegion);
+
+    /* Remove parts clipped by parents from the window region */
+    if (!is_region_empty(ParentRegion))
+        subtract_region(NewRegion, NewRegion, ParentRegion);
+
+    DPRINT("New visible region:\n");
+    //SwmDumpRegion(NewRegion);
+
+    /* Compute the difference between old and new visible
+       regions into the temp region */
+    DiffRegion = create_empty_region();
+    subtract_region(DiffRegion, CalcWindow->Visible, NewRegion);
+
+    DPRINT("Diff between old and new:\n");
+    //SwmDumpRegion(DiffRegion);
+
+    /* Now get rid of the old visible region */
+    free_region(CalcWindow->Visible);
+    CalcWindow->Visible = NewRegion;
+
+    /* Show the difference if any */
+    //if (!is_region_empty(DiffRegion))
+    //    SwmInvalidateRegion(CalcWindow, DiffRegion, NULL);
+
+    /* Free allocated temporary regions */
+    free_region(DiffRegion);
+    free_region(ParentRegion);
+}
+
+VOID
+NTAPI
+SwmClipAllWindows()
+{
+    PLIST_ENTRY Current;
+    PSWM_WINDOW Window;
+
+    /* Traverse the list to find our window */
     Current = SwmWindows.Flink;
     while(Current != &SwmWindows)
     {
@@ -194,37 +286,8 @@
             continue;
         }
 
-        /* Get window's region */
-        WindowRegion = create_empty_region();
-        set_region_rect(WindowRegion, &Window->Window);
-
-        /* Region to mark invisible for this window = Update region X Window region */
-        intersect_region(WindowRegion, WindowRegion, Region);
-
-        /* Check if it's empty */
-        if (!is_region_empty(WindowRegion))
-        {
-            DPRINT("Invalidating region\n");
-            SwmDumpRegion(WindowRegion);
-            DPRINT("of window %x\n", Window->hwnd);
-
-            /* If it's not empty, subtract it from the source region */
-            subtract_region(Region, Region, WindowRegion);
-
-            /* And add it to this window's visible region */
-            union_region(Window->Visible, Window->Visible, WindowRegion);
-
-            /* Invalidate this region of target window */
-            SwmInvalidateRegion(Window, WindowRegion, NULL);
-
-            DPRINT("Rest of the update region is:\n");
-            SwmDumpRegion(Region);
-        }
-
-        free_region(WindowRegion);
-
-        /* If region to update became empty, quit */
-        if (is_region_empty(Region)) break;
+        /* Recalculate visibility for this window */
+        SwmRecalculateVisibility(Window);
 
         /* Advance to the next window */
         Current = Current->Flink;
@@ -233,17 +296,13 @@
 
 VOID
 NTAPI
-SwmRecalculateVisibility(PSWM_WINDOW CalcWindow)
+SwmDrawAllWindows()
 {
     PLIST_ENTRY Current;
     PSWM_WINDOW Window;
-    struct region *Region = create_empty_region();
-    struct region *WindowRegion = create_empty_region();
-
-    set_region_rect(WindowRegion, &CalcWindow->Window);
-
-    /* Compile a total region of visible regions of "higher" windows */
-    Current = &CalcWindow->Entry;
+
+    /* Traverse the list to find our window */
+    Current = SwmWindows.Flink;
     while(Current != &SwmWindows)
     {
         Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry);
@@ -252,25 +311,16 @@
         if (Window->Hidden)
         {
             /* Advance to the next window */
-            Current = Current->Blink;
+            Current = Current->Flink;
             continue;
         }
 
-        union_region(Region, Region, Window->Visible);
-
-        /* Advance to the previous window */
-        Current = Current->Blink;
-    }
-
-    /* Crop the region against target window */
-    intersect_region(Region, Region, WindowRegion);
-
-    /* Subtract result from target window's visible region */
-    subtract_region(CalcWindow->Visible, WindowRegion, Region);
-
-    /* Free allocated temporary regions */
-    free_region(Region);
-    free_region(WindowRegion);
+        /* Draw its visible region */
+        SwmInvalidateRegion(Window, Window->Visible, NULL);
+
+        /* Advance to the next window */
+        Current = Current->Flink;
+    }
 }
 
 VOID
@@ -279,8 +329,8 @@
 {
     PSWM_WINDOW Win;
 
-    DPRINT("SwmAddWindow %x\n", hWnd);
-    DPRINT("rect (%d,%d)-(%d,%d)\n", WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom);
+    DPRINT1("SwmAddWindow %x\n", hWnd);
+    DPRINT1("rect (%d,%d)-(%d,%d)\n", WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom);
 
     /* Acquire the lock */
     SwmAcquire();
@@ -298,15 +348,16 @@
     set_region_rect(Win->Visible, &Win->Window);
 
     /* Now go through the list and remove this rect from all underlying windows visible region */
-    SwmMarkInvisible(Win->Visible);
+    //SwmMarkInvisible(Win->Visible);
 
     InsertHeadList(&SwmWindows, &Win->Entry);
 
     /* Now ensure it is visible on screen */
     SwmInvalidateRegion(Win, Win->Visible, &Win->Window);
 
+    SwmClipAllWindows();
+
     //SwmDumpWindows();
-    //SwmDebugDrawWindows();
 
     /* Release the lock */
     SwmRelease();
@@ -346,10 +397,10 @@
     Desktop->Visible = create_empty_region();
     set_region_rect(Desktop->Visible, &Desktop->Window);
 
-    /* Now go through the list and remove this rect from all underlying windows visible region */
-    SwmMarkInvisible(Desktop->Visible);
-
     InsertTailList(&SwmWindows, &Desktop->Entry);
+
+    /* Calculate windows clipping */
+    SwmClipAllWindows();
 
     /* Now ensure it is visible on screen */
     SwmInvalidateRegion(Desktop, Desktop->Visible, &Desktop->Window);
@@ -394,7 +445,7 @@
     /* Acquire the lock */
     SwmAcquire();
 
-    DPRINT("SwmRemoveWindow %x\n", hWnd);
+    DPRINT1("SwmRemoveWindow %x\n", hWnd);
 
     /* Allocate entry */
     Win = SwmFindByHwnd(hWnd);
@@ -410,12 +461,14 @@
     RemoveEntryList(&Win->Entry);
 
     /* Mark this region as visible in other window */
-    SwmMarkVisible(Win->Visible);
+    //SwmMarkVisible(Win->Visible);
 
     /* Free the entry */
     free_region(Win->Visible);
     ExFreePool(Win);
 
+    SwmClipAllWindows();
+
     /* Release the lock */
     SwmRelease();
 }
@@ -450,7 +503,9 @@
 SwmBringToFront(PSWM_WINDOW SwmWin)
 {
     PSWM_WINDOW Previous;
+#ifdef INCREMENTAL_CLIPPING
     struct region *OldVisible;
+#endif
 
     /* Save previous focus window */
     Previous = SwmGetTopWindow();
@@ -470,6 +525,7 @@
     /* Add it to the head of the list */
     InsertHeadList(&SwmWindows, &SwmWin->Entry);
 
+#ifdef INCREMENTAL_CLIPPING
     /* Subtract old visible from the new one to find region for updating */
     OldVisible = create_empty_region();
     set_region_rect(OldVisible, &SwmWin->Window);
@@ -492,6 +548,16 @@
 
     /* Update previous window's visible region */
     SwmRecalculateVisibility(Previous);
+#else
+    /* Make it fully visible */
+    free_region(SwmWin->Visible);
+    SwmWin->Visible = create_empty_region();
+    set_region_rect(SwmWin->Visible, &SwmWin->Window);
+
+    // TODO: Redraw only new parts!
+    SwmClipAllWindows();
+    SwmInvalidateRegion(SwmWin, SwmWin->Visible, NULL);
+#endif
 }
 
 VOID
@@ -530,8 +596,10 @@
 SwmPosChanged(HWND hWnd, const RECT *WindowRect, const RECT *OldRect)
 {
     PSWM_WINDOW SwmWin;
+#ifdef INCREMENTAL_CLIPPING
     struct region *NewRegion;
     rectangle_t WinRect;
+#endif
 
     /* Acquire the lock */
     SwmAcquire();
@@ -555,12 +623,14 @@
         SwmRelease();
         return;
     }
+//DPRINT1("rect (%d,%d)-(%d,%d)\n", TmpRect.left, TmpRect.top, TmpRect.right, TmpRect.bottom);
+    DPRINT1("SwmPosChanged hwnd %x, new rect (%d,%d)-(%d,%d)\n", hWnd, WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom);
 
     SwmWin->Window.left = WindowRect->left;
     SwmWin->Window.top = WindowRect->top;
     SwmWin->Window.right = WindowRect->right;
     SwmWin->Window.bottom = WindowRect->bottom;
-
+#ifdef INCREMENTAL_CLIPPING
     //SwmDebugDrawWindows();
 
     /* Assure the moving window is foreground */
@@ -587,6 +657,9 @@
 
     /* Redraw window itself too */
     //SwmInvalidateRegion(SwmWin, SwmWin->Visible, NULL);
+#else
+    SwmClipAllWindows();
+#endif
 
     /* Release the lock */
     SwmRelease();
@@ -597,6 +670,7 @@
 SwmShowWindow(HWND hWnd, BOOLEAN Show)
 {
     PSWM_WINDOW Win;
+    struct region *OldRegion;
 
     /* Acquire the lock */
     SwmAcquire();
@@ -615,22 +689,28 @@
     if (Show && Win->Hidden)
     {
         /* Change state from hidden to visible */
-        DPRINT("Unhiding %x\n", Win->hwnd);
+        DPRINT1("Unhiding %x\n", Win->hwnd);
         Win->Hidden = FALSE;
         SwmBringToFront(Win);
     }
     else if (!Show && !Win->Hidden)
     {
-        DPRINT("Hiding %x\n", Win->hwnd);
+        DPRINT1("Hiding %x\n", Win->hwnd);
         /* Change state from visible to hidden */
         Win->Hidden = TRUE;
 
-        /* Mark its region as visible */
-        SwmMarkVisible(Win->Visible);
-
-        /* Its visible region is now empty */
-        free_region(Win->Visible);
+        /* Save its visible region */
+        OldRegion = Win->Visible;
+
+        /* Put an empty visible region */
         Win->Visible = create_empty_region();
+
+        /* Recalculate clipping */
+        SwmClipAllWindows();
+
+        /* Show region which was taken by this window and free it */
+        SwmPaintRegion(OldRegion);
+        free_region(OldRegion);
     }
 
     /* Release the lock */




More information about the Ros-diffs mailing list