server: Store a separate flag for windows that need to be erased in WM_PAINT.

This avoids the need to invalidate the window after WM_ERASEBKGND.
This commit is contained in:
Alexandre Julliard 2007-08-27 16:41:08 +02:00
parent 5bd497f3ca
commit df13cee288
4 changed files with 40 additions and 20 deletions

View File

@ -243,7 +243,7 @@ static HRGN send_ncpaint( HWND hwnd, HWND *child, UINT *flags )
static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn,
RECT *clip_rect, HDC *hdc_ret )
{
BOOL need_erase = FALSE;
BOOL need_erase = (flags & UPDATE_DELAYED_ERASE) != 0;
HDC hdc = 0;
RECT dummy;
@ -263,12 +263,7 @@ static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn,
if (type != NULLREGION)
need_erase = !SendMessageW( hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0 );
}
if (!hdc_ret)
{
if (need_erase && hwnd != GetDesktopWindow()) /* FIXME: mark it as needing erase again */
RedrawWindow( hwnd, clip_rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN );
USER_Driver->pReleaseDC( hwnd, hdc, TRUE );
}
if (!hdc_ret) USER_Driver->pReleaseDC( hwnd, hdc, TRUE );
}
if (hdc_ret) *hdc_ret = hdc;
@ -287,6 +282,7 @@ void erase_now( HWND hwnd, UINT rdw_flags )
{
HWND child = 0;
HRGN hrgn;
BOOL need_erase = FALSE;
/* loop while we find a child to repaint */
for (;;)
@ -295,12 +291,13 @@ void erase_now( HWND hwnd, UINT rdw_flags )
if (rdw_flags & RDW_NOCHILDREN) flags |= UPDATE_NOCHILDREN;
else if (rdw_flags & RDW_ALLCHILDREN) flags |= UPDATE_ALLCHILDREN;
if (need_erase) flags |= UPDATE_DELAYED_ERASE;
if (!(hrgn = send_ncpaint( hwnd, &child, &flags ))) break;
send_erase( child, flags, hrgn, NULL, NULL );
need_erase = send_erase( child, flags, hrgn, NULL, NULL );
if (!flags) break; /* nothing more to do */
if (rdw_flags & RDW_NOCHILDREN) break;
if ((rdw_flags & RDW_NOCHILDREN) && !need_erase) break;
}
}
@ -736,7 +733,11 @@ INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
POINT offset;
retval = CombineRgn( hrgn, update_rgn, 0, RGN_COPY );
send_erase( hwnd, flags, update_rgn, NULL, NULL );
if (send_erase( hwnd, flags, update_rgn, NULL, NULL ))
{
flags = UPDATE_DELAYED_ERASE;
get_update_flags( hwnd, NULL, &flags );
}
/* map region to client coordinates */
offset.x = offset.y = 0;
ScreenToClient( hwnd, &offset );
@ -753,6 +754,7 @@ BOOL WINAPI GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
{
UINT flags = UPDATE_NOCHILDREN;
HRGN update_rgn;
BOOL need_erase;
if (erase) flags |= UPDATE_NONCLIENT | UPDATE_ERASE;
@ -768,10 +770,11 @@ BOOL WINAPI GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
ReleaseDC( hwnd, hdc );
}
}
send_erase( hwnd, flags, update_rgn, NULL, NULL );
need_erase = send_erase( hwnd, flags, update_rgn, NULL, NULL );
/* check if we still have an update region */
flags = UPDATE_PAINT | UPDATE_NOCHILDREN;
if (need_erase) flags |= UPDATE_DELAYED_ERASE;
return (get_update_flags( hwnd, NULL, &flags ) && (flags & UPDATE_PAINT));
}

View File

@ -3073,6 +3073,7 @@ struct get_update_region_reply
#define UPDATE_ALLCHILDREN 0x10
#define UPDATE_NOCHILDREN 0x20
#define UPDATE_NOREGION 0x40
#define UPDATE_DELAYED_ERASE 0x80
@ -4730,6 +4731,6 @@ union generic_reply
struct make_process_system_reply make_process_system_reply;
};
#define SERVER_PROTOCOL_VERSION 309
#define SERVER_PROTOCOL_VERSION 310
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2256,6 +2256,7 @@ enum message_type
#define UPDATE_ALLCHILDREN 0x10 /* force repaint of all children */
#define UPDATE_NOCHILDREN 0x20 /* don't try to repaint any children */
#define UPDATE_NOREGION 0x40 /* don't return a region, only the flags */
#define UPDATE_DELAYED_ERASE 0x80 /* still needs erase after BeginPaint */
/* Update the z order of a window so that a given rectangle is fully visible */

View File

@ -88,9 +88,10 @@ struct window
char extra_bytes[1]; /* extra bytes storage */
};
#define PAINT_INTERNAL 0x01 /* internal WM_PAINT pending */
#define PAINT_ERASE 0x02 /* needs WM_ERASEBKGND */
#define PAINT_NONCLIENT 0x04 /* needs WM_NCPAINT */
#define PAINT_INTERNAL 0x01 /* internal WM_PAINT pending */
#define PAINT_ERASE 0x02 /* needs WM_ERASEBKGND */
#define PAINT_NONCLIENT 0x04 /* needs WM_NCPAINT */
#define PAINT_DELAYED_ERASE 0x08 /* still needs erase after WM_ERASEBKGND */
/* growable array of user handles */
struct user_handle_array
@ -978,7 +979,7 @@ static void set_update_region( struct window *win, struct region *region )
inc_window_paint_count( win, -1 );
free_region( win->update_region );
}
win->paint_flags &= ~(PAINT_ERASE | PAINT_NONCLIENT);
win->paint_flags &= ~(PAINT_ERASE | PAINT_DELAYED_ERASE | PAINT_NONCLIENT);
win->update_region = NULL;
if (region) free_region( region );
}
@ -1122,7 +1123,7 @@ static void redraw_window( struct window *win, struct region *region, int frame,
set_update_region( win, tmp );
}
if (flags & RDW_NOFRAME) validate_non_client( win );
if (flags & RDW_NOERASE) win->paint_flags &= ~PAINT_ERASE;
if (flags & RDW_NOERASE) win->paint_flags &= ~(PAINT_ERASE | PAINT_DELAYED_ERASE);
}
}
@ -1178,11 +1179,19 @@ static unsigned int get_update_flags( struct window *win, unsigned int flags )
}
if (flags & UPDATE_PAINT)
{
if (win->update_region) ret |= UPDATE_PAINT;
if (win->update_region)
{
if (win->paint_flags & PAINT_DELAYED_ERASE) ret |= UPDATE_DELAYED_ERASE;
ret |= UPDATE_PAINT;
}
}
if (flags & UPDATE_INTERNALPAINT)
{
if (win->paint_flags & PAINT_INTERNAL) ret |= UPDATE_INTERNALPAINT;
if (win->paint_flags & PAINT_INTERNAL)
{
ret |= UPDATE_INTERNALPAINT;
if (win->paint_flags & PAINT_DELAYED_ERASE) ret |= UPDATE_DELAYED_ERASE;
}
}
return ret;
}
@ -1943,6 +1952,12 @@ DECL_HANDLER(get_update_region)
}
}
if (flags & UPDATE_DELAYED_ERASE) /* this means that the previous call didn't erase */
{
if (from_child) from_child->paint_flags |= PAINT_DELAYED_ERASE;
else win->paint_flags |= PAINT_DELAYED_ERASE;
}
reply->flags = get_window_update_flags( win, from_child, flags, &win );
reply->child = win->handle;
@ -1975,7 +1990,7 @@ DECL_HANDLER(get_update_region)
if (reply->flags & UPDATE_NONCLIENT) validate_non_client( win );
if (reply->flags & UPDATE_ERASE)
{
win->paint_flags &= ~PAINT_ERASE;
win->paint_flags &= ~(PAINT_ERASE | PAINT_DELAYED_ERASE);
/* desktop window only gets erased, not repainted */
if (is_desktop_window(win)) validate_whole_window( win );
}