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