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