Alexandre Julliard : server: Also crop the update region of children when moving a window.

Alexandre Julliard julliard at winehq.org
Mon May 12 07:12:23 CDT 2008


Module: wine
Branch: master
Commit: bc25119c6ecb5e733be2a32b56cd24cfd78d3d06
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bc25119c6ecb5e733be2a32b56cd24cfd78d3d06

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon May 12 12:28:57 2008 +0200

server: Also crop the update region of children when moving a window.

---

 dlls/user32/tests/msg.c |   13 ++++++++++++
 server/window.c         |   50 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 3499f69..da353f9 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -5811,6 +5811,19 @@ static void test_paint_messages(void)
     SetRectRgn( hrgn, 10, 10, 40, 40 );
     check_update_rgn( hchild, hrgn );
 
+    /* moving parent off-screen does too */
+    SetRect( &rect, 0, 0, 100, 100 );
+    RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN );
+    SetRectRgn( hrgn, 0, 0, 100, 100 );
+    check_update_rgn( hparent, hrgn );
+    SetRectRgn( hrgn, 10, 10, 40, 40 );
+    check_update_rgn( hchild, hrgn );
+    MoveWindow( hparent, -20, -20, 200, 200, FALSE );
+    SetRectRgn( hrgn, 20, 20, 100, 100 );
+    check_update_rgn( hparent, hrgn );
+    SetRectRgn( hrgn, 30, 30, 40, 40 );
+    check_update_rgn( hchild, hrgn );
+
     DestroyWindow( hparent );
     ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
     flush_sequence();
diff --git a/server/window.c b/server/window.c
index 4c3b3ba..3a67b8d 100644
--- a/server/window.c
+++ b/server/window.c
@@ -1097,6 +1097,45 @@ static int add_update_region( struct window *win, struct region *region )
 }
 
 
+/* crop the update region of children to the specified rectangle, in client coords */
+static void crop_children_update_region( struct window *win, rectangle_t *rect )
+{
+    struct window *child;
+    struct region *tmp = create_empty_region();
+    rectangle_t child_rect;
+
+    LIST_FOR_EACH_ENTRY( child, &win->children, struct window, entry )
+    {
+        if (!(child->style & WS_VISIBLE)) continue;
+        if (!rect)  /* crop everything out */
+        {
+            crop_children_update_region( child, NULL );
+            set_update_region( child, NULL );
+            continue;
+        }
+
+        /* nothing to do if child is completely inside rect */
+        if (child->window_rect.left >= rect->left &&
+            child->window_rect.top >= rect->top &&
+            child->window_rect.right <= rect->right &&
+            child->window_rect.bottom <= rect->bottom) continue;
+
+        /* map to child client coords and crop grand-children */
+        child_rect = *rect;
+        offset_rect( &child_rect, -child->client_rect.left, -child->client_rect.top );
+        crop_children_update_region( child, &child_rect );
+
+        /* now crop the child itself */
+        if (!child->update_region) continue;
+        if (!(tmp = create_empty_region())) continue;
+        set_region_rect( tmp, rect );
+        offset_region( tmp, -child->window_rect.left, -child->window_rect.top );
+        if (intersect_region( tmp, child->update_region, tmp )) set_update_region( child, tmp );
+        else free_region( tmp );
+    }
+}
+
+
 /* validate the non client area of a window */
 static void validate_non_client( struct window *win )
 {
@@ -1521,6 +1560,17 @@ static void set_window_pos( struct window *win, struct window *previous,
         else set_update_region( win, NULL ); /* visible rect is empty */
     }
 
+    /* crop children regions to the new window rect */
+
+    if (get_window_visible_rect( win, &rect, 0 ))
+    {
+        /* map to client coords */
+        offset_rect( &rect, win->window_rect.left - win->client_rect.left,
+                     win->window_rect.top - win->client_rect.top );
+        crop_children_update_region( win, &rect );
+    }
+    else crop_children_update_region( win, NULL );
+
     if (swp_flags & SWP_NOREDRAW) goto done;  /* do not repaint anything */
 
     /* expose the whole non-client area if it changed in any way */




More information about the wine-cvs mailing list