From a67f1484e05419aafe3cd4791babd4cbae41791f Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sun, 27 Mar 2005 13:54:09 +0000
Subject: [PATCH] made Update() recursive under wxGTK2 (doesn't work for wxGTK1
 because Refresh() is not recursive htere neither) and documented its
 behaviour

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33091 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/window.tex | 24 +++++++++++-----------
 src/gtk/window.cpp       | 44 ++++++++++++++++++++++++++--------------
 src/gtk1/window.cpp      | 44 ++++++++++++++++++++++++++--------------
 3 files changed, 70 insertions(+), 42 deletions(-)

diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex
index d7d90fd9f2..c307195d6e 100644
--- a/docs/latex/wx/window.tex
+++ b/docs/latex/wx/window.tex
@@ -2222,13 +2222,13 @@ or frame).
 
 \membersection{wxWindow::Refresh}\label{wxwindowrefresh}
 
-\func{virtual void}{Refresh}{\param{bool}{ eraseBackground = {\tt true}}, \param{const wxRect* }{rect
-= NULL}}
+\func{virtual void}{Refresh}{\param{bool}{ eraseBackground = {\tt true}}, \param{const wxRect* }{rect = NULL}}
 
-Causes this window, and all of its children recursively, to be repainted. Note
-that repainting doesn't happen immediately but only during the next event loop
-iteration, if you need to update the window immediately you should use 
-\helpref{Update}{wxwindowupdate} instead.
+Causes this window, and all of its children recursively (except under wxGTK1
+where this is not implemented), to be repainted. Note that repainting doesn't
+happen immediately but only during the next event loop iteration, if you need
+to update the window immediately you should use \helpref{Update}{wxwindowupdate} 
+instead.
 
 \wxheading{Parameters}
 
@@ -3489,12 +3489,12 @@ This function is currently only implemented under MSW.
 
 \func{virtual void}{Update}{\void}
 
-Calling this method immediately repaints the invalidated area of the window
-while this would usually only happen when the flow of control returns to the
-event loop. Notice that this function doesn't refresh the window and does
-nothing if the window hadn't been already repainted. Use 
-\helpref{Refresh}{wxwindowrefresh} first if you want to immediately redraw the
-window unconditionally.
+Calling this method immediately repaints the invalidated area of the window and
+all of its children recursively while this would usually only happen when the
+flow of control returns to the event loop. Notice that this function doesn't
+refresh the window and does nothing if the window hadn't been already
+repainted. Use \helpref{Refresh}{wxwindowrefresh} first if you want to
+immediately redraw the window unconditionally.
 
 
 \membersection{wxWindow::UpdateWindowUI}\label{wxwindowupdatewindowui}
diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp
index 312f41eadb..fd76da760f 100644
--- a/src/gtk/window.cpp
+++ b/src/gtk/window.cpp
@@ -3927,35 +3927,38 @@ void wxWindowGTK::WarpPointer( int x, int y )
 
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
-    if (!m_widget) return;
-    if (!m_widget->window) return;
+    if (!m_widget)
+        return;
+    if (!m_widget->window)
+        return;
 
 #ifndef __WXGTK20__
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    wxRect myRect(0,0,0,0);
+    wxRect myRect;
     if (m_wxwindow && rect)
     {
         myRect.SetSize(wxSize( m_wxwindow->allocation.width,
                                m_wxwindow->allocation.height));
-        myRect.Intersect(*rect);
-        if (!myRect.width || !myRect.height)
+        if ( myRect.Intersect(*rect).IsEmpty() )
+        {
             // nothing to do, rectangle is empty
             return;
+        }
+
         rect = &myRect;
     }
 
+    // schedule the area for later updating in GtkUpdate()
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
     {
         if (rect)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_clearRegion.Clear();
             m_clearRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
@@ -3965,7 +3968,6 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
@@ -3982,7 +3984,6 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_updateRegion.Clear();
             m_updateRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
@@ -3991,24 +3992,27 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
             gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
         }
     }
-#else
+#else // GTK+ 2
     if (m_wxwindow)
     {
+        GdkRectangle gdk_rect,
+                    *p;
         if (rect)
         {
-            GdkRectangle gdk_rect;
             gdk_rect.x = rect->x;
             gdk_rect.y = rect->y;
             gdk_rect.width = rect->width;
             gdk_rect.height = rect->height;
-            gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, &gdk_rect, TRUE );
+            p = &gdk_rect;
         }
-        else
+        else // invalidate everything
         {
-            gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, NULL, TRUE );
+            p = NULL;
         }
+
+        gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
     }
-#endif
+#endif // GTK+ 1/2
 }
 
 void wxWindowGTK::Update()
@@ -4031,6 +4035,16 @@ void wxWindowGTK::GtkUpdate()
     if (!m_updateRegion.IsEmpty())
         GtkSendPaintEvents();
 #endif
+
+    // for consistency with other platforms (and also because it's convenient
+    // to be able to update an entire TLW by calling Update() only once), we
+    // should also update all our children here
+    for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        node->GetData()->GtkUpdate();
+    }
 }
 
 void wxWindowGTK::GtkSendPaintEvents()
diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp
index 312f41eadb..fd76da760f 100644
--- a/src/gtk1/window.cpp
+++ b/src/gtk1/window.cpp
@@ -3927,35 +3927,38 @@ void wxWindowGTK::WarpPointer( int x, int y )
 
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
-    if (!m_widget) return;
-    if (!m_widget->window) return;
+    if (!m_widget)
+        return;
+    if (!m_widget->window)
+        return;
 
 #ifndef __WXGTK20__
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    wxRect myRect(0,0,0,0);
+    wxRect myRect;
     if (m_wxwindow && rect)
     {
         myRect.SetSize(wxSize( m_wxwindow->allocation.width,
                                m_wxwindow->allocation.height));
-        myRect.Intersect(*rect);
-        if (!myRect.width || !myRect.height)
+        if ( myRect.Intersect(*rect).IsEmpty() )
+        {
             // nothing to do, rectangle is empty
             return;
+        }
+
         rect = &myRect;
     }
 
+    // schedule the area for later updating in GtkUpdate()
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
     {
         if (rect)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_clearRegion.Clear();
             m_clearRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
@@ -3965,7 +3968,6 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
@@ -3982,7 +3984,6 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_updateRegion.Clear();
             m_updateRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
@@ -3991,24 +3992,27 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
             gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
         }
     }
-#else
+#else // GTK+ 2
     if (m_wxwindow)
     {
+        GdkRectangle gdk_rect,
+                    *p;
         if (rect)
         {
-            GdkRectangle gdk_rect;
             gdk_rect.x = rect->x;
             gdk_rect.y = rect->y;
             gdk_rect.width = rect->width;
             gdk_rect.height = rect->height;
-            gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, &gdk_rect, TRUE );
+            p = &gdk_rect;
         }
-        else
+        else // invalidate everything
         {
-            gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, NULL, TRUE );
+            p = NULL;
         }
+
+        gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
     }
-#endif
+#endif // GTK+ 1/2
 }
 
 void wxWindowGTK::Update()
@@ -4031,6 +4035,16 @@ void wxWindowGTK::GtkUpdate()
     if (!m_updateRegion.IsEmpty())
         GtkSendPaintEvents();
 #endif
+
+    // for consistency with other platforms (and also because it's convenient
+    // to be able to update an entire TLW by calling Update() only once), we
+    // should also update all our children here
+    for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        node->GetData()->GtkUpdate();
+    }
 }
 
 void wxWindowGTK::GtkSendPaintEvents()
-- 
2.50.0

