UT2003 Regression - Patch at last :-))

Alexandre Julliard julliard at winehq.org
Thu May 26 15:06:30 CDT 2005


Alexandre Julliard <julliard at winehq.org> writes:

> "Ann and Jason Edmeades" <us at the-edmeades.demon.co.uk> writes:
> 
> > What about instead of the send_ncpaind/send_erase when child==prev (assuming
> > this to be the more 'unusual' case and not the norm) I build a list of the
> > hwnds and validate their update region. When the loop completes, for each
> > hwnd left in the list I do the send_ncpaint/send_erase processing?
> > 
> > Without removing the update region there's no way to step further in the
> > list, if I understand the problem correctly?
> 
> Yes, but that's what needs to be fixed, we need to make progress even
> if the update region is not validated. We will then get a WM_PAINT in
> the main message loop, which I believe is what we want.

Try something like this:

Index: dlls/user/painting.c
===================================================================
RCS file: /opt/cvs-commit/wine/dlls/user/painting.c,v
retrieving revision 1.29
diff -u -p -r1.29 painting.c
--- dlls/user/painting.c	13 May 2005 14:03:06 -0000	1.29
+++ dlls/user/painting.c	26 May 2005 19:56:42 -0000
@@ -99,8 +99,9 @@ static HRGN get_update_region( HWND hwnd
 
         SERVER_START_REQ( get_update_region )
         {
-            req->window = hwnd;
-            req->flags  = *flags;
+            req->window     = hwnd;
+            req->from_child = 0;
+            req->flags      = *flags;
             wine_server_set_reply( req, data->Buffer, size );
             if (!(status = wine_server_call( req )))
             {
@@ -135,8 +136,9 @@ static BOOL get_update_flags( HWND hwnd,
 
     SERVER_START_REQ( get_update_region )
     {
-        req->window = hwnd;
-        req->flags  = *flags | UPDATE_NOREGION;
+        req->window     = hwnd;
+        req->from_child = child ? *child : 0;
+        req->flags      = *flags | UPDATE_NOREGION;
         if ((ret = !wine_server_call_err( req )))
         {
             if (child) *child = reply->child;
@@ -319,7 +321,7 @@ static void erase_now( HWND hwnd, UINT r
  */
 static void update_now( HWND hwnd, UINT rdw_flags )
 {
-    HWND prev = 0, child;
+    HWND child = 0;
 
     /* desktop window never gets WM_PAINT, only WM_ERASEBKGND */
     if (hwnd == GetDesktopWindow()) erase_now( hwnd, rdw_flags | RDW_NOCHILDREN );
@@ -335,22 +337,7 @@ static void update_now( HWND hwnd, UINT 
         if (!get_update_flags( hwnd, &child, &flags )) break;
         if (!flags) break;  /* nothing more to do */
 
-        if (child == prev)  /* same window again, didn't get repainted properly */
-        {
-            UINT erase_flags = UPDATE_NONCLIENT | UPDATE_ERASE | UPDATE_NOCHILDREN;
-            HRGN hrgn;
-
-            TRACE( "%p not repainted properly, erasing\n", child );
-            if ((hrgn = send_ncpaint( child, NULL, &erase_flags )))
-                send_erase( child, erase_flags, hrgn, NULL, NULL );
-
-            prev = 0;
-        }
-        else
-        {
-            prev = child;
-            SendMessageW( child, WM_PAINT, 0, 0 );
-        }
+        SendMessageW( child, WM_PAINT, 0, 0 );
         if (rdw_flags & RDW_NOCHILDREN) break;
     }
 }
Index: server/protocol.def
===================================================================
RCS file: /opt/cvs-commit/wine/server/protocol.def,v
retrieving revision 1.138
diff -u -p -r1.138 protocol.def
--- server/protocol.def	24 May 2005 12:32:18 -0000	1.138
+++ server/protocol.def	26 May 2005 19:57:30 -0000
@@ -1953,6 +1953,7 @@ enum message_type
 /* Get the window update region */
 @REQ(get_update_region)
     user_handle_t  window;        /* handle to the window */
+    user_handle_t  from_child;    /* child to start searching from */
     unsigned int   flags;         /* update flags (see below) */
 @REPLY
     user_handle_t  child;         /* child to repaint (or window itself) */
Index: server/window.c
===================================================================
RCS file: /opt/cvs-commit/wine/server/window.c,v
retrieving revision 1.54
diff -u -p -r1.54 window.c
--- server/window.c	26 May 2005 12:28:07 -0000	1.54
+++ server/window.c	26 May 2005 19:57:46 -0000
@@ -1046,33 +1046,72 @@ static unsigned int get_update_flags( st
 
 
 /* iterate through the children of the given window until we find one with some update flags */
-static unsigned int get_child_update_flags( struct window *win, unsigned int flags,
-                                            struct window **child )
+static unsigned int get_child_update_flags( struct window *win, struct window *from_child,
+                                            unsigned int flags, struct window **child )
 {
     struct window *ptr;
     unsigned int ret = 0;
 
+    /* first make sure we want to iterate children at all */
+
+    if (win->style & WS_MINIMIZE) return 0;
+
+    /* note: the WS_CLIPCHILDREN test is the opposite of the invalidation case,
+     * here we only want to repaint children of windows that clip them, others
+     * need to wait for WM_PAINT to be done in the parent first.
+     */
+    if (!(flags & UPDATE_ALLCHILDREN) && !(win->style & WS_CLIPCHILDREN)) return 0;
+
     LIST_FOR_EACH_ENTRY( ptr, &win->children, struct window, entry )
     {
+        if (from_child)  /* skip all children until from_child is found */
+        {
+            if (ptr == from_child) from_child = NULL;
+            continue;
+        }
         if (!(ptr->style & WS_VISIBLE)) continue;
         if ((ret = get_update_flags( ptr, flags )) != 0)
         {
             *child = ptr;
             break;
         }
-        if (ptr->style & WS_MINIMIZE) continue;
+        if ((ret = get_child_update_flags( ptr, NULL, flags, child ))) break;
+    }
+    return ret;
+}
 
-        /* Note: the WS_CLIPCHILDREN test is the opposite of the invalidation case,
-         * here we only want to repaint children of windows that clip them, others
-         * need to wait for WM_PAINT to be done in the parent first.
-         */
-        if (!(flags & UPDATE_NOCHILDREN) &&
-            ((flags & UPDATE_ALLCHILDREN) || (ptr->style & WS_CLIPCHILDREN)))
+/* iterate through children and siblings of the given window until we find one with some update flags */
+static unsigned int get_window_update_flags( struct window *win, struct window *from_child,
+                                             unsigned int flags, struct window **child )
+{
+    unsigned int ret;
+
+    /* check window itself (only if not restarting from a child) */
+
+    if (!from_child)
+    {
+        if ((ret = get_update_flags( win, flags )))
         {
-            if ((ret = get_child_update_flags( ptr, flags, child ))) break;
+            *child = win;
+            return ret;
         }
+        from_child = win;
     }
-    return ret;
+
+    /* now check children */
+
+    if (flags & UPDATE_NOCHILDREN) return 0;
+    if ((ret = get_child_update_flags( from_child, NULL, flags, child ))) return ret;
+
+    /* then check siblings and parent siblings */
+
+    while (from_child->parent && from_child != win)
+    {
+        if ((ret = get_child_update_flags( from_child->parent, from_child, flags, child )))
+            return ret;
+        from_child = from_child->parent;
+    }
+    return 0;
 }
 
 
@@ -1667,11 +1706,28 @@ DECL_HANDLER(get_update_region)
 {
     rectangle_t *data;
     unsigned int flags = req->flags;
+    struct window *from_child = NULL;
     struct window *win = get_window( req->window );
 
     reply->flags = 0;
     if (!win || !is_visible( win )) return;
 
+    if (req->from_child)
+    {
+        struct window *ptr;
+
+        if (!(from_child = get_window( req->from_child ))) return;
+
+        /* make sure from_child is a child of win */
+        ptr = from_child;
+        while (ptr && ptr != win) ptr = ptr->parent;
+        if (!ptr)
+        {
+            set_error( STATUS_INVALID_PARAMETER );
+            return;
+        }
+    }
+
     if ((flags & UPDATE_NONCLIENT) && !(flags & (UPDATE_PAINT|UPDATE_INTERNALPAINT)))
     {
         /* non-client painting must be delayed if one of the parents is going to
@@ -1685,17 +1741,7 @@ DECL_HANDLER(get_update_region)
         }
     }
 
-    if (!(reply->flags = get_update_flags( win, flags )))
-    {
-        /* if window doesn't need any repaint, check the children */
-        if (!(flags & UPDATE_NOCHILDREN) &&
-            ((flags & UPDATE_ALLCHILDREN) || (win->style & WS_CLIPCHILDREN)) &&
-            !(win->style & WS_MINIMIZE))
-        {
-            reply->flags = get_child_update_flags( win, flags, &win );
-        }
-    }
-
+    reply->flags = get_window_update_flags( win, from_child, flags, &win );
     reply->child = win->handle;
 
     if (flags & UPDATE_NOREGION) return;

-- 
Alexandre Julliard
julliard at winehq.org



More information about the wine-devel mailing list