]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
Various compile fixes.
[wxWidgets.git] / src / gtk1 / window.cpp
index ccb09b9a12abb22bac1d52c5cf0a9d5fe37a2079..b2941feb0a3e4cf27b0fa462099cb00df48acae0 100644 (file)
@@ -385,34 +385,34 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
 
     if (win->m_hasScrolling)
     {
 
     if (win->m_hasScrolling)
     {
-            GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
+        GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
 
 
-            GtkRequisition vscroll_req;
-            vscroll_req.width = 2;
-            vscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
-                (scroll_window->vscrollbar, &vscroll_req );
+        GtkRequisition vscroll_req;
+        vscroll_req.width = 2;
+        vscroll_req.height = 2;
+        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
+            (scroll_window->vscrollbar, &vscroll_req );
 
 
-            GtkRequisition hscroll_req;
-            hscroll_req.width = 2;
-            hscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
-                (scroll_window->hscrollbar, &hscroll_req );
+        GtkRequisition hscroll_req;
+        hscroll_req.width = 2;
+        hscroll_req.height = 2;
+        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
+            (scroll_window->hscrollbar, &hscroll_req );
 
 
-            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
+        GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
 
 
-            if (scroll_window->vscrollbar_visible)
-            {
-                dw += vscroll_req.width;
-                dw += scroll_class->scrollbar_spacing;
-            }
+        if (scroll_window->vscrollbar_visible)
+        {
+            dw += vscroll_req.width;
+            dw += scroll_class->scrollbar_spacing;
+        }
 
 
-            if (scroll_window->hscrollbar_visible)
-            {
-                dh += hscroll_req.height;
-                dh += scroll_class->scrollbar_spacing;
-            }
-    }
+        if (scroll_window->hscrollbar_visible)
+        {
+            dh += hscroll_req.height;
+            dh += scroll_class->scrollbar_spacing;
+        }
+}
 
     int dx = 0;
     int dy = 0;
 
     int dx = 0;
     int dy = 0;
@@ -800,68 +800,7 @@ static int gtk_window_expose_callback( GtkWidget *widget,
                                   gdk_event->area.width,
                                   gdk_event->area.height );
 
                                   gdk_event->area.width,
                                   gdk_event->area.height );
 
-    if (gdk_event->count == 0)
-    {
-        win->m_clipPaintRegion = TRUE;
-
-        wxWindowDC dc(win);
-        dc.SetClippingRegion(win->GetUpdateRegion());
-        wxEraseEvent eevent( win->GetId(), &dc );
-        eevent.SetEventObject( win );
-#if 1
-        (void)win->GetEventHandler()->ProcessEvent(eevent);
-#else // 0
-        if (!win->GetEventHandler()->ProcessEvent(eevent))
-        {
-            wxClientDC dc( win );
-            dc.SetBrush( wxBrush( win->GetBackgroundColour(), wxSOLID ) );
-            dc.SetPen( *wxTRANSPARENT_PEN );
-
-            wxRegionIterator upd( win->GetUpdateRegion() );
-            while (upd)
-            {
-                dc.DrawRectangle( upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
-                upd ++;
-            }
-        }
-#endif // 1/0
-
-        wxNcPaintEvent eventNc( win->GetId() );
-        eventNc.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent( eventNc );
-
-        wxPaintEvent event( win->GetId() );
-        event.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent( event );
-
-        win->GetUpdateRegion().Clear();
-
-        win->m_clipPaintRegion = FALSE;
-    }
-
-    /* The following code will result in all window-less widgets
-       being redrawn if the wxWindows class is given a chance to
-       paint *anything* because it will then be allowed to paint
-       over the window-less widgets */
-    GList *children = pizza->children;
-    while (children)
-    {
-        GtkPizzaChild *child = (GtkPizzaChild*) children->data;
-        children = children->next;
-
-        GdkEventExpose child_event = *gdk_event;
-
-        if (GTK_WIDGET_NO_WINDOW (child->widget) &&
-            GTK_WIDGET_DRAWABLE (child->widget) /* &&
-            gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
-        {
-            child_event.area.x = child->widget->allocation.x;
-            child_event.area.y = child->widget->allocation.y;
-            child_event.area.width = child->widget->allocation.width;
-            child_event.area.height = child->widget->allocation.height;
-            gtk_widget_event (child->widget, (GdkEvent*) &child_event);
-        }
-    }
+    // Actual redrawing takes place in idle time.
 
     return TRUE;
 }
 
     return TRUE;
 }
@@ -870,11 +809,11 @@ static int gtk_window_expose_callback( GtkWidget *widget,
 // "event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
 // "event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
-/* GTK thinks it is clever and filters out a certain amount of "unneeded"
-   expose events. We need them, of course, so we override the main event
-   procedure in GtkWidget by giving our own handler for all system events.
-   There, we look for expose events ourselves whereas all other events are
-   handled normally. */
+// GTK thinks it is clever and filters out a certain amount of "unneeded"
+// expose events. We need them, of course, so we override the main event
+// procedure in GtkWidget by giving our own handler for all system events.
+// There, we look for expose events ourselves whereas all other events are
+// handled normally.
 
 gint gtk_window_event_event_callback( GtkWidget *widget,
                                       GdkEventExpose *event,
 
 gint gtk_window_event_event_callback( GtkWidget *widget,
                                       GdkEventExpose *event,
@@ -893,8 +832,8 @@ gint gtk_window_event_event_callback( GtkWidget *widget,
 // "draw" of m_wxwindow
 //-----------------------------------------------------------------------------
 
 // "draw" of m_wxwindow
 //-----------------------------------------------------------------------------
 
-/* This callback is a complete replacement of the gtk_pizza_draw() function,
-   which disabled. */
+// This callback is a complete replacement of the gtk_pizza_draw() function,
+// which disabled.
 
 static void gtk_window_draw_callback( GtkWidget *widget,
                                       GdkRectangle *rect,
 
 static void gtk_window_draw_callback( GtkWidget *widget,
                                       GdkRectangle *rect,
@@ -905,6 +844,8 @@ static void gtk_window_draw_callback( GtkWidget *widget,
     if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (g_isIdle)
         wxapp_install_idle_handler();
 
+    // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
+    // there are no child windows.
     if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
         (win->GetChildren().GetCount() == 0))
     {
     if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
         (win->GetChildren().GetCount() == 0))
     {
@@ -954,59 +895,23 @@ static void gtk_window_draw_callback( GtkWidget *widget,
 
     win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
 
 
     win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
 
-    win->m_clipPaintRegion = TRUE;
-
-    wxWindowDC dc(win);
-    dc.SetClippingRegion(win->GetUpdateRegion());
-    wxEraseEvent eevent( win->GetId(), &dc );
-    eevent.SetEventObject( win );
-
-#if 1
-    (void)win->GetEventHandler()->ProcessEvent(eevent);
-#else
-    if (!win->GetEventHandler()->ProcessEvent(eevent))
-    {
-        if (!win->GetEventHandler()->ProcessEvent(eevent))
-        {
-            wxClientDC dc( win );
-            dc.SetBrush( wxBrush( win->GetBackgroundColour(), wxSOLID ) );
-            dc.SetPen( *wxTRANSPARENT_PEN );
-
-            wxRegionIterator upd( win->GetUpdateRegion() );
-            while (upd)
-            {
-                dc.DrawRectangle( upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
-                upd ++;
-            }
-        }
-    }
-#endif
-
-    wxNcPaintEvent eventNc( win->GetId() );
-    eventNc.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( eventNc );
-
-    wxPaintEvent event( win->GetId() );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
-
-    win->GetUpdateRegion().Clear();
-
-    win->m_clipPaintRegion = FALSE;
-
+    // Actual redrawing takes place in idle time.
 
 
+#ifndef __WXUNIVERSAL__
+    // Redraw child widgets
     GList *children = pizza->children;
     while (children)
     {
     GList *children = pizza->children;
     while (children)
     {
-            GtkPizzaChild *child = (GtkPizzaChild*) children->data;
-            children = children->next;
+        GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+        children = children->next;
 
 
-            GdkRectangle child_area;
-            if (gtk_widget_intersect (child->widget, rect, &child_area))
-            {
-                gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
-            }
+        GdkRectangle child_area;
+        if (gtk_widget_intersect (child->widget, rect, &child_area))
+        {
+            gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
+        }
     }
     }
+#endif
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
@@ -1356,9 +1261,9 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
     InitMouseEvent( win, event, gdk_event );
 
     AdjustEventButtonState(event);
     InitMouseEvent( win, event, gdk_event );
 
     AdjustEventButtonState(event);
-    
+
     // wxListBox actually get mouse events from the item
     // wxListBox actually get mouse events from the item
-    
+
     if (win->m_isListBox)
     {
         event.m_x += widget->allocation.x;
     if (win->m_isListBox)
     {
         event.m_x += widget->allocation.x;
@@ -1489,7 +1394,7 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
     AdjustEventButtonState(event);
 
     // wxListBox actually get mouse events from the item
     AdjustEventButtonState(event);
 
     // wxListBox actually get mouse events from the item
-    
+
     if (win->m_isListBox)
     {
         event.m_x += widget->allocation.x;
     if (win->m_isListBox)
     {
         event.m_x += widget->allocation.x;
@@ -2370,7 +2275,7 @@ void wxWindowGTK::Init()
 
     m_noExpose = FALSE;
     m_nativeSizeEvent = FALSE;
 
     m_noExpose = FALSE;
     m_nativeSizeEvent = FALSE;
-    
+
     m_hasScrolling = FALSE;
     m_isScrolling = FALSE;
 
     m_hasScrolling = FALSE;
     m_isScrolling = FALSE;
 
@@ -2545,7 +2450,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
     if (m_parent)
         m_parent->DoAddChild( this );
 
     if (m_parent)
         m_parent->DoAddChild( this );
-        
+
     m_focusWidget = m_wxwindow;
 
     PostCreation();
     m_focusWidget = m_wxwindow;
 
     PostCreation();
@@ -2639,7 +2544,7 @@ bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const w
 void wxWindowGTK::PostCreation()
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
 void wxWindowGTK::PostCreation()
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
-    
+
     if (m_wxwindow)
     {
         if (!m_noExpose)
     if (m_wxwindow)
     {
         if (!m_noExpose)
@@ -2821,10 +2726,15 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
              if (height == -1) m_height = 26;
         }
 
              if (height == -1) m_height = 26;
         }
 
-        if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
-        if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
-        if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
-        if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
+        int minWidth = GetMinWidth(),
+            minHeight = GetMinHeight(),
+            maxWidth = GetMaxWidth(),
+            maxHeight = GetMaxHeight();
+
+        if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
+        if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
+        if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
+        if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
 
         int border = 0;
         int bottom_border = 0;
 
         int border = 0;
         int bottom_border = 0;
@@ -2872,6 +2782,10 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
 
 void wxWindowGTK::OnInternalIdle()
 {
 
 void wxWindowGTK::OnInternalIdle()
 {
+    // Update invalidated regions.
+    Update();
+    
+    // Synthetize activate events.
     if ( g_sendActivateEvent != -1 )
     {
         bool activate = g_sendActivateEvent != 0;
     if ( g_sendActivateEvent != -1 )
     {
         bool activate = g_sendActivateEvent != 0;
@@ -3087,7 +3001,7 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
         dx = pizza->xoffset;
         dy = pizza->yoffset;
     }
         dx = pizza->xoffset;
         dy = pizza->yoffset;
     }
-    
+
     if (x) (*x) = m_x - dx;
     if (y) (*y) = m_y - dy;
 }
     if (x) (*x) = m_x - dx;
     if (y) (*y) = m_y - dy;
 }
@@ -3280,7 +3194,7 @@ void wxWindowGTK::SetFocus()
            // ?
         }
     }
            // ?
         }
     }
-    
+
 #if 0
     wxPrintf( "SetFocus finished in " );
     if (GetClassInfo() && GetClassInfo()->GetClassName())
 #if 0
     wxPrintf( "SetFocus finished in " );
     if (GetClassInfo() && GetClassInfo()->GetClassName())
@@ -3384,8 +3298,8 @@ void wxWindowGTK::WarpPointer( int x, int y )
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
-    /* we provide this function ourselves as it is
-       missing in GDK (top of this file)  */
+    // We provide this function ourselves as it is
+    // missing in GDK (top of this file).
 
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
 
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
@@ -3412,86 +3326,144 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (rect)
         {
     {
         if (rect)
         {
-            gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
-                                   rect->x, rect->y,
-                                   rect->width, rect->height );
+            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
+            m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
         {
         }
         else
         {
-            gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
+            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
+            m_clearRegion.Clear();
+            m_clearRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
     }
 
         }
     }
 
-    /* there is no GTK equivalent of "draw only, don't clear" so we
-       invent our own in the GtkPizza widget */
-
-    if (!rect)
+    if (rect)
     {
         if (m_wxwindow)
         {
     {
         if (m_wxwindow)
         {
-
-/*
-            GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
-            gboolean old_clear = pizza->clear_on_draw;
-            gtk_pizza_set_clear( pizza, FALSE );
-            gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
-            gtk_pizza_set_clear( pizza, old_clear );
-*/
-            GdkEventExpose gdk_event;
-            gdk_event.type = GDK_EXPOSE;
-            gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
-            gdk_event.count = 0;
-            gdk_event.area.x = 0;
-            gdk_event.area.y = 0;
-            gdk_event.area.width = m_wxwindow->allocation.width;
-            gdk_event.area.height = m_wxwindow->allocation.height;
-            gtk_window_expose_callback( m_wxwindow, &gdk_event, (wxWindow *)this );
+            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
+            m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
         {
         }
         else
         {
-            gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
+            GdkRectangle gdk_rect;
+            gdk_rect.x = rect->x;
+            gdk_rect.y = rect->y;
+            gdk_rect.width = rect->width;
+            gdk_rect.height = rect->height;
+            gtk_widget_draw( m_widget, &gdk_rect );
         }
     }
     else
     {
         }
     }
     else
     {
-
         if (m_wxwindow)
         {
         if (m_wxwindow)
         {
-/*
-            GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
-            gboolean old_clear = pizza->clear_on_draw;
-            gtk_pizza_set_clear( pizza, FALSE );
+            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
+            m_updateRegion.Clear();
+            m_updateRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
+        }
+        else
+        {
+            gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
+        }
+    }
+}
 
 
-            GdkRectangle gdk_rect;
-            gdk_rect.x = rect->x;
-            gdk_rect.y = rect->y;
-            gdk_rect.width = rect->width;
-            gdk_rect.height = rect->height;
-            gtk_widget_draw( m_wxwindow, &gdk_rect );
-            gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
+void wxWindowGTK::Update()
+{
+    if (!m_updateRegion.IsEmpty())
+    {
+        GtkSendPaintEvents();
+    }
+}
 
 
-            gtk_pizza_set_clear( pizza, old_clear );
-*/
+void wxWindowGTK::GtkSendPaintEvents()
+{
+    if (!m_wxwindow)
+    {
+        m_clearRegion.Clear();
+        m_updateRegion.Clear();
+        return;
+    }
+
+    m_clipPaintRegion = TRUE;
+
+    if (!m_clearRegion.IsEmpty())
+    {
+        wxWindowDC dc( (wxWindow*)this );
+        dc.SetClippingRegion( m_clearRegion );
+        
+        wxEraseEvent erase_event( GetId(), &dc );
+        erase_event.SetEventObject( this );
+    
+        if (!GetEventHandler()->ProcessEvent(erase_event))
+        {
+            wxRegionIterator upd( m_clearRegion );
+            while (upd)
+            {
+                gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
+                                       upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
+                upd ++;
+            }
+        }
+        m_clearRegion.Clear();
+    }
+
+    wxNcPaintEvent nc_paint_event( GetId() );
+    nc_paint_event.SetEventObject( this );
+    GetEventHandler()->ProcessEvent( nc_paint_event );
+
+    wxPaintEvent paint_event( GetId() );
+    paint_event.SetEventObject( this );
+    GetEventHandler()->ProcessEvent( paint_event );
+
+    m_clipPaintRegion = FALSE;
+
+#ifndef __WXUNIVERSAL__
+    // The following code will result in all window-less widgets
+    // being redrawn because the wxWindows class is allowed to
+    // paint over the window-less widgets.
+    
+    GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
+    
+    GList *children = pizza->children;
+    while (children)
+    {
+        GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+        children = children->next;
+
+        if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+            GTK_WIDGET_DRAWABLE (child->widget))
+        {
+            // Get intersection of widget area and update region
+            wxRegion region( m_updateRegion );
+            
             GdkEventExpose gdk_event;
             gdk_event.type = GDK_EXPOSE;
             GdkEventExpose gdk_event;
             gdk_event.type = GDK_EXPOSE;
-            gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
+            gdk_event.window = pizza->bin_window;
             gdk_event.count = 0;
             gdk_event.count = 0;
-            gdk_event.area.x = rect->x;
-            gdk_event.area.y = rect->y;
-            gdk_event.area.width = rect->width;
-            gdk_event.area.height = rect->height;
-            gtk_window_expose_callback( m_wxwindow, &gdk_event, (wxWindow *)this );
-        }
-        else
-        {
-            GdkRectangle gdk_rect;
-            gdk_rect.x = rect->x;
-            gdk_rect.y = rect->y;
-            gdk_rect.width = rect->width;
-            gdk_rect.height = rect->height;
-            gtk_widget_draw( m_widget, &gdk_rect );
+            
+            wxRegionIterator upd( m_updateRegion );
+            while (upd)
+            {
+                GdkRectangle rect;
+                rect.x = upd.GetX();
+                rect.y = upd.GetY();
+                rect.width = upd.GetWidth();
+                rect.height = upd.GetHeight();
+                
+                if (gtk_widget_intersect (child->widget, &rect, &gdk_event.area))
+                {
+                    gtk_widget_event (child->widget, (GdkEvent*) &gdk_event);
+                }
+                
+                upd ++;
+            }
         }
     }
         }
     }
+#endif
+
+    m_updateRegion.Clear();
 }
 
 void wxWindowGTK::Clear()
 }
 
 void wxWindowGTK::Clear()
@@ -3628,7 +3600,7 @@ GtkStyle *wxWindowGTK::GetWidgetStyle()
 
 void wxWindowGTK::SetWidgetStyle()
 {
 
 void wxWindowGTK::SetWidgetStyle()
 {
-#if DISABLE_STYLE_IF_BROKEN_THEM
+#if DISABLE_STYLE_IF_BROKEN_THEME
     if (m_widget->style->engine_data)
     {
         static bool s_warningPrinted = FALSE;
     if (m_widget->style->engine_data)
     {
         static bool s_warningPrinted = FALSE;
@@ -3755,9 +3727,9 @@ static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
 static gint gs_pop_x = 0;
 static gint gs_pop_y = 0;
 
 static gint gs_pop_x = 0;
 static gint gs_pop_y = 0;
 
-static void wxPopupMenuPositionCallback( GtkMenu *menu,
-                                         gint *x, gint *y,
-                                         gpointer WXUNUSED(user_data) )
+extern "C" void wxPopupMenuPositionCallback( GtkMenu *menu,
+                                             gint *x, gint *y,
+                                             gpointer WXUNUSED(user_data) )
 {
     // ensure that the menu appears entirely on screen
     GtkRequisition req;
 {
     // ensure that the menu appears entirely on screen
     GtkRequisition req;
@@ -3872,7 +3844,7 @@ bool wxWindowGTK::SetFont( const wxFont &font )
     return TRUE;
 }
 
     return TRUE;
 }
 
-void wxWindowGTK::CaptureMouse()
+void wxWindowGTK::DoCaptureMouse()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
@@ -3901,12 +3873,14 @@ void wxWindowGTK::CaptureMouse()
     g_captureWindowHasMouse = TRUE;
 }
 
     g_captureWindowHasMouse = TRUE;
 }
 
-void wxWindowGTK::ReleaseMouse()
+void wxWindowGTK::DoReleaseMouse()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
     wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") );
 
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
     wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") );
 
+    g_captureWindow = (wxWindowGTK*) NULL;
+
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
         window = GTK_PIZZA(m_wxwindow)->bin_window;
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
         window = GTK_PIZZA(m_wxwindow)->bin_window;
@@ -3917,7 +3891,6 @@ void wxWindowGTK::ReleaseMouse()
         return;
 
     gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
         return;
 
     gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
-    g_captureWindow = (wxWindowGTK*) NULL;
 }
 
 /* static */
 }
 
 /* static */
@@ -4089,13 +4062,39 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
 
 
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
 
+    // No scrolling requested.
     if ((dx == 0) && (dy == 0)) return;
     if ((dx == 0) && (dy == 0)) return;
+    
+    if (!m_updateRegion.IsEmpty())
+    {
+        m_updateRegion.Offset( dx, dy );
+        
+        int cw = 0;
+        int ch = 0;
+        GetClientSize( &cw, &ch );
+        m_updateRegion.Intersect( 0, 0, cw, ch );
+    }
+    
+    if (!m_clearRegion.IsEmpty())
+    {
+        m_clearRegion.Offset( dx, dy );
+        
+        int cw = 0;
+        int ch = 0;
+        GetClientSize( &cw, &ch );
+        m_clearRegion.Intersect( 0, 0, cw, ch );
+    }
+    
+#if 1
 
     m_clipPaintRegion = TRUE;
 
     m_clipPaintRegion = TRUE;
+    
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
+    
     m_clipPaintRegion = FALSE;
 
     m_clipPaintRegion = FALSE;
 
-/*
+#else
+
     if (m_children.GetCount() > 0)
     {
         gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
     if (m_children.GetCount() > 0)
     {
         gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
@@ -4145,7 +4144,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
         gdk_gc_unref( m_scrollGC );
     }
 
         gdk_gc_unref( m_scrollGC );
     }
-*/
+#endif
 }
 
 // Find the wxWindow at the current mouse position, also returning the mouse
 }
 
 // Find the wxWindow at the current mouse position, also returning the mouse