Alexandre Julliard : server:
Store a separate flag for windows that need to be erased in WM_PAINT.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Aug 27 13:57:12 CDT 2007
Module: wine
Branch: master
Commit: df13cee288de4b57614253db9bcd7700bbfa99cf
URL: http://source.winehq.org/git/wine.git/?a=commit;h=df13cee288de4b57614253db9bcd7700bbfa99cf
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Aug 27 16:41:08 2007 +0200
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.
---
dlls/user32/painting.c | 25 ++++++++++++++-----------
include/wine/server_protocol.h | 3 ++-
server/protocol.def | 1 +
server/window.c | 31 +++++++++++++++++++++++--------
4 files changed, 40 insertions(+), 20 deletions(-)
diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c
index 22dd6c2..9ba4a7a 100644
--- a/dlls/user32/painting.c
+++ b/dlls/user32/painting.c
@@ -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));
}
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index e0f7f8b..71d0709 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -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 */
diff --git a/server/protocol.def b/server/protocol.def
index 6e13cb2..aaf6c2e 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -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 */
diff --git a/server/window.c b/server/window.c
index 8971dc6..14d6468 100644
--- a/server/window.c
+++ b/server/window.c
@@ -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 );
}
More information about the wine-cvs
mailing list