]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Route data from wxDataViewModel in a wxVariant
[wxWidgets.git] / src / gtk / window.cpp
index bb9ab32d19b9eced98b8bb7cf9089ffeabd3b581..4dbeb3449891dc24b43bb133d36c9f7f9a94d8f6 100644 (file)
@@ -47,6 +47,7 @@
 #include "wx/settings.h"
 #include "wx/log.h"
 #include "wx/fontutil.h"
+#include "wx/stattext.h"
 
 #ifdef __WXDEBUG__
     #include "wx/thread.h"
 #include "wx/math.h"
 #include <ctype.h>
 
+// FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0
+#include <gtk/gtkversion.h>
+#if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0)
+#undef GTK_DISABLE_DEPRECATED
+#endif
+
 #include "wx/gtk/private.h"
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkkeysyms.h>
@@ -358,23 +365,25 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
 
     if (win->HasFlag(wxRAISED_BORDER))
     {
-        gtk_draw_shadow( widget->style,
-                         widget->window,
-                         GTK_STATE_NORMAL,
-                         GTK_SHADOW_OUT,
-                         dx, dy,
-                         widget->allocation.width-dw, widget->allocation.height-dh );
+        gtk_paint_shadow (widget->style,
+                          widget->window,
+                          GTK_STATE_NORMAL,
+                          GTK_SHADOW_OUT,
+                          NULL, NULL, NULL, // FIXME: No clipping?
+                          dx, dy,
+                          widget->allocation.width-dw, widget->allocation.height-dh );
         return;
     }
 
     if (win->HasFlag(wxSUNKEN_BORDER))
     {
-        gtk_draw_shadow( widget->style,
-                         widget->window,
-                         GTK_STATE_NORMAL,
-                         GTK_SHADOW_IN,
-                         dx, dy,
-                         widget->allocation.width-dw, widget->allocation.height-dh );
+        gtk_paint_shadow (widget->style,
+                          widget->window,
+                          GTK_STATE_NORMAL,
+                          GTK_SHADOW_IN,
+                          NULL, NULL, NULL, // FIXME: No clipping?
+                          dx, dy,
+                          widget->allocation.width-dw, widget->allocation.height-dh );
         return;
     }
 
@@ -828,6 +837,10 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
     event.m_rawFlags = 0;
 #if wxUSE_UNICODE
     event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval);
+    if ( gdk_event->type == GDK_KEY_PRESS ||  gdk_event->type == GDK_KEY_RELEASE )
+    {
+        event.m_uniChar = toupper(event.m_uniChar);
+    }
 #endif
     wxGetMousePosition( &x, &y );
     win->ScreenToClient( &x, &y );
@@ -976,7 +989,12 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     bool ret = false;
     bool return_after_IM = false;
 
-    if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) == false )
+    if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
+    {
+        // Emit KEY_DOWN event
+        ret = win->GetEventHandler()->ProcessEvent( event );
+    }
+    else
     {
         // Return after IM processing as we cannot do
         // anything with it anyhow.
@@ -1011,9 +1029,6 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     if (return_after_IM)
         return false;
 
-    // Emit KEY_DOWN event
-    ret = win->GetEventHandler()->ProcessEvent( event );
-
 #if wxUSE_ACCEL
     if (!ret)
     {
@@ -1062,6 +1077,16 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 
             event.m_keyCode = key_code;
 
+            // To conform to the docs we need to translate Ctrl-alpha
+            // characters to values in the range 1-26.
+            if (event.ControlDown() && key_code >= 'a' && key_code <= 'z' )
+            {
+                event.m_keyCode = key_code - 'a' + 1;
+#if wxUSE_UNICODE
+                event.m_uniChar = event.m_keyCode;
+#endif
+            }               
+
             // Implement OnCharHook by checking ancestor top level windows
             wxWindow *parent = win;
             while (parent && !parent->IsTopLevel())
@@ -1147,7 +1172,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 
     if (ret)
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
+        g_signal_stop_emission_by_name (widget, "key_press_event");
         return TRUE;
     }
 
@@ -1196,6 +1221,17 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
 #else
         event.m_keyCode = *pstr;
 #endif  // wxUSE_UNICODE
+
+        // To conform to the docs we need to translate Ctrl-alpha
+        // characters to values in the range 1-26.
+        if (event.ControlDown() && *pstr >= 'a' && *pstr <= 'z' )
+        {
+            event.m_keyCode = *pstr - 'a' + 1;
+#if wxUSE_UNICODE
+            event.m_uniChar = event.m_keyCode;
+#endif  
+        }               
+
         if (parent)
         {
             event.SetEventType( wxEVT_CHAR_HOOK );
@@ -1242,7 +1278,7 @@ static gint gtk_window_key_release_callback( GtkWidget *widget,
     if ( !win->GetEventHandler()->ProcessEvent( event ) )
         return FALSE;
 
-    gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
+    g_signal_stop_emission_by_name (widget, "key_release_event");
     return TRUE;
 }
 }
@@ -1550,7 +1586,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
+        g_signal_stop_emission_by_name (widget, "button_press_event");
         return TRUE;
     }
 
@@ -1629,7 +1665,7 @@ static gint gtk_window_button_release_callback( GtkWidget *widget,
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
+        g_signal_stop_emission_by_name (widget, "button_release_event");
         return TRUE;
     }
 
@@ -1703,9 +1739,18 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
         win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
     }
 
+    if ( !g_captureWindow )
+    {
+        wxSetCursorEvent cevent( event.m_x, event.m_y );
+        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        {
+            // Rewrite cursor handling here (away from idle).
+        }
+    }
+    
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
+        g_signal_stop_emission_by_name (widget, "motion_notify_event");
         return TRUE;
     }
 
@@ -1762,7 +1807,7 @@ static gint gtk_window_wheel_callback (GtkWidget * widget,
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "scroll_event" );
+        g_signal_stop_emission_by_name (widget, "scroll_event");
         return TRUE;
     }
 
@@ -1805,9 +1850,9 @@ static bool DoSendFocusEvents(wxWindow *win)
 }
 
 extern "C" {
-static gint gtk_window_focus_in_callback( GtkWidget *widget,
-                                          GdkEvent *WXUNUSED(event),
-                                          wxWindow *win )
+static gboolean gtk_window_focus_in_callback( GtkWidget *widget,
+                                              GdkEvent *WXUNUSED(event),
+                                              wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1837,20 +1882,25 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
     }
 #endif // wxUSE_CARET
 
+    gboolean ret = FALSE;
+
     // does the window itself think that it has the focus?
     if ( !win->m_hasFocus )
     {
         // not yet, notify it
         win->m_hasFocus = true;
 
-        if ( DoSendFocusEvents(win) )
-        {
-           gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
-           return TRUE;
-        }
+        (void)DoSendFocusEvents(win);
+        
+        ret = true;
     }
 
-    return FALSE;
+    // Disable default focus handling for custom windows
+    // since the default GTK+ handler issues a repaint
+    if (win->m_wxwindow)
+        return ret;
+        
+    return false;
 }
 }
 
@@ -1859,7 +1909,9 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk_event, wxWindowGTK *win )
+static gboolean gtk_window_focus_out_callback( GtkWidget *widget,
+                                               GdkEventFocus *gdk_event,
+                                               wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1893,6 +1945,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
     }
 #endif // wxUSE_CARET
 
+    gboolean ret = FALSE;
+
     // don't send the window a kill focus event if it thinks that it doesn't
     // have focus already
     if ( win->m_hasFocus )
@@ -1902,14 +1956,17 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
         wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
         event.SetEventObject( win );
 
-        // even if we did process the event in wx code, still let GTK itself
-        // process it too as otherwise bad things happen, especially in GTK2
-        // where the text control simply aborts the program if it doesn't get
-        // the matching focus out event
         (void)win->GetEventHandler()->ProcessEvent( event );
+        
+        ret = true;
     }
-
-    return FALSE;
+    
+    // Disable default focus handling for custom windows
+    // since the default GTK+ handler issues a repaint
+    if (win->m_wxwindow)
+        return ret;
+           
+    return false;
 }
 }
 
@@ -1918,10 +1975,10 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static
-gint gtk_window_enter_callback( GtkWidget *widget,
-                                GdkEventCrossing *gdk_event,
-                                wxWindowGTK *win )
+static gboolean
+gtk_window_enter_callback( GtkWidget *widget,
+                           GdkEventCrossing *gdk_event,
+                           wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1948,9 +2005,18 @@ gint gtk_window_enter_callback( GtkWidget *widget,
     event.m_x = x + pt.x;
     event.m_y = y + pt.y;
 
+    if ( !g_captureWindow )
+    {
+        wxSetCursorEvent cevent( event.m_x, event.m_y );
+        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        {
+            // Rewrite cursor handling here (away from idle).
+        }
+    }
+    
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-       gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
+       g_signal_stop_emission_by_name (widget, "enter_notify_event");
        return TRUE;
     }
 
@@ -1963,7 +2029,10 @@ gint gtk_window_enter_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
+static gboolean
+gtk_window_leave_callback( GtkWidget *widget,
+                           GdkEventCrossing *gdk_event,
+                           wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -2002,7 +2071,7 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
+        g_signal_stop_emission_by_name (widget, "leave_notify_event");
         return TRUE;
     }
 
@@ -2016,7 +2085,6 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
 extern "C" {
 static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
-                                         SCROLLBAR_CBACK_ARG
                                          wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
@@ -2033,7 +2101,7 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
 
     win->m_oldVerticalPos = adjust->value;
 
-    wxEventType         command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->vscrollbar));
+    wxEventType command = GtkScrollWinTypeToWx(GTK_SCROLL_JUMP);
 
     int value = (int)(adjust->value+0.5);
 
@@ -2049,7 +2117,6 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
 
 extern "C" {
 static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
-                                         SCROLLBAR_CBACK_ARG
                                          wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
@@ -2063,7 +2130,7 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
     float diff = adjust->value - win->m_oldHorizontalPos;
     if (fabs(diff) < 0.2) return;
 
-    wxEventType         command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->hscrollbar));
+    wxEventType command = GtkScrollWinTypeToWx(GTK_SCROLL_JUMP);
 
     win->m_oldHorizontalPos = adjust->value;
 
@@ -2555,39 +2622,35 @@ bool wxWindowGTK::Create( wxWindow *parent,
     m_vAdjust->step_increment = 1.0;
     m_vAdjust->page_increment = 1.0;
     m_vAdjust->page_size = 5.0;
-    gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
+    g_signal_emit_by_name (m_vAdjust, "changed");
     m_hAdjust->lower = 0.0;
     m_hAdjust->upper = 1.0;
     m_hAdjust->value = 0.0;
     m_hAdjust->step_increment = 1.0;
     m_hAdjust->page_increment = 1.0;
     m_hAdjust->page_size = 5.0;
-    gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
+    g_signal_emit_by_name (m_hAdjust, "changed");
 
     // these handlers block mouse events to any window during scrolling such as
     // motion events and prevent GTK and wxWidgets from fighting over where the
     // slider should be
-
-    gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
-          (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
-          (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
-          (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
-          (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
+    g_signal_connect (scrolledWindow->vscrollbar, "button_press_event",
+                      G_CALLBACK (gtk_scrollbar_button_press_callback), this);
+    g_signal_connect (scrolledWindow->hscrollbar, "button_press_event",
+                      G_CALLBACK (gtk_scrollbar_button_press_callback), this);
+    g_signal_connect (scrolledWindow->vscrollbar, "button_release_event",
+                      G_CALLBACK (gtk_scrollbar_button_release_callback), this);
+    g_signal_connect (scrolledWindow->hscrollbar, "button_release_event",
+                      G_CALLBACK (gtk_scrollbar_button_release_callback), this);
 
     // these handlers get notified when screen updates are required either when
     // scrolling or when the window size (and therefore scrollbar configuration)
     // has changed
 
-    gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
-          (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
-    gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
-          (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
+    g_signal_connect (m_hAdjust, "value_changed",
+                      G_CALLBACK (gtk_window_hscroll_callback), this);
+    g_signal_connect (m_vAdjust, "value_changed",
+                      G_CALLBACK (gtk_window_vscroll_callback), this);
 
     gtk_widget_show( m_wxwindow );
 
@@ -2621,10 +2684,12 @@ wxWindowGTK::~wxWindowGTK()
     // propagated to this (soon to be) dead object
     if (m_focusWidget != NULL)
     {
-        gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget),
-            (GtkSignalFunc) gtk_window_focus_in_callback, (gpointer) this );
-        gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget),
-            (GtkSignalFunc) gtk_window_focus_out_callback, (gpointer) this );
+        g_signal_handlers_disconnect_by_func (m_focusWidget,
+                                              (gpointer) gtk_window_focus_in_callback,
+                                              this);
+        g_signal_handlers_disconnect_by_func (m_focusWidget,
+                                              (gpointer) gtk_window_focus_out_callback,
+                                              this);
     }
 
     if (m_widget)
@@ -2680,10 +2745,10 @@ void wxWindowGTK::PostCreation()
 
             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
 
-            gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
-                GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
+            g_signal_connect (m_wxwindow, "expose_event",
+                              G_CALLBACK (gtk_window_expose_callback), this);
 
-            // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
+            gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
         }
 
         // Create input method handler
@@ -2692,13 +2757,12 @@ void wxWindowGTK::PostCreation()
         // Cannot handle drawing preedited text yet
         gtk_im_context_set_use_preedit( m_imData->context, FALSE );
 
-        g_signal_connect (G_OBJECT (m_imData->context), "commit",
+        g_signal_connect (m_imData->context, "commit",
                           G_CALLBACK (gtk_wxwindow_commit_cb), this);
 
         // these are called when the "sunken" or "raised" borders are drawn
-        gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
-          GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
-
+        g_signal_connect (m_widget, "expose_event",
+                          G_CALLBACK (gtk_window_own_expose_callback), this);
     }
 
     // focus handling
@@ -2708,11 +2772,20 @@ void wxWindowGTK::PostCreation()
         if (m_focusWidget == NULL)
             m_focusWidget = m_widget;
 
-        gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_in_event",
-            GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
-
-        gtk_signal_connect_after( GTK_OBJECT(m_focusWidget), "focus_out_event",
-            GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+        if (m_wxwindow)
+        {
+            g_signal_connect (m_focusWidget, "focus_in_event",
+                          G_CALLBACK (gtk_window_focus_in_callback), this);
+            g_signal_connect (m_focusWidget, "focus_out_event",
+                                G_CALLBACK (gtk_window_focus_out_callback), this);
+        }
+        else
+        {
+            g_signal_connect_after (m_focusWidget, "focus_in_event",
+                          G_CALLBACK (gtk_window_focus_in_callback), this);
+            g_signal_connect_after (m_focusWidget, "focus_out_event",
+                                G_CALLBACK (gtk_window_focus_out_callback), this);
+        }
     }
 
     // connect to the various key and mouse handlers
@@ -2723,31 +2796,31 @@ void wxWindowGTK::PostCreation()
 
     /* We cannot set colours, fonts and cursors before the widget has
        been realized, so we do this directly after realization */
-    gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
-                            GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
+    g_signal_connect (connect_widget, "realize",
+                      G_CALLBACK (gtk_window_realized_callback), this);
 
     if (m_wxwindow)
     {
         // Catch native resize events
-        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
-                            GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
+        g_signal_connect (m_wxwindow, "size_allocate",
+                          G_CALLBACK (gtk_window_size_callback), this);
 
         // Initialize XIM support
-        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
-                            GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
+        g_signal_connect (m_wxwindow, "realize",
+                          G_CALLBACK (gtk_wxwindow_realized_callback), this);
 
         // And resize XIM window
-        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
-                            GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
+        g_signal_connect (m_wxwindow, "size_allocate",
+                          G_CALLBACK (gtk_wxwindow_size_callback), this);
     }
 
     if (GTK_IS_COMBO(m_widget))
     {
         GtkCombo *gcombo = GTK_COMBO(m_widget);
 
-        gtk_signal_connect( GTK_OBJECT(gcombo->entry), "size_request",
-                            GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback),
-                            (gpointer) this );
+        g_signal_connect (gcombo->entry, "size_request",
+                          G_CALLBACK (wxgtk_combo_size_request_callback),
+                          this);
     }
     else
     {
@@ -2755,9 +2828,9 @@ void wxWindowGTK::PostCreation()
         // GTK controls, such as the toolbar. With this callback, the
         // toolbar gets to know the correct size (the one set by the
         // programmer). Sadly, it misbehaves for wxComboBox.
-        gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
-                            GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback),
-                            (gpointer) this );
+        g_signal_connect (m_widget, "size_request",
+                          G_CALLBACK (wxgtk_window_size_request_callback),
+                          this);
     }
 
     InheritAttributes();
@@ -2772,31 +2845,24 @@ void wxWindowGTK::PostCreation()
 
 void wxWindowGTK::ConnectWidget( GtkWidget *widget )
 {
-    gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
-      GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
-      GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
-      GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
-      GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
-      GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "scroll_event",
-      GTK_SIGNAL_FUNC(gtk_window_wheel_callback), (gpointer)this );
-    g_signal_connect(widget, "popup_menu",
-        G_CALLBACK(wxgtk_window_popup_menu_callback), this);
-
-    gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
-      GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
-      GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
+    g_signal_connect (widget, "key_press_event",
+                      G_CALLBACK (gtk_window_key_press_callback), this);
+    g_signal_connect (widget, "key_release_event",
+                      G_CALLBACK (gtk_window_key_release_callback), this);
+    g_signal_connect (widget, "button_press_event",
+                      G_CALLBACK (gtk_window_button_press_callback), this);
+    g_signal_connect (widget, "button_release_event",
+                      G_CALLBACK (gtk_window_button_release_callback), this);
+    g_signal_connect (widget, "motion_notify_event",
+                      G_CALLBACK (gtk_window_motion_notify_callback), this);
+    g_signal_connect (widget, "scroll_event",
+                      G_CALLBACK (gtk_window_wheel_callback), this);
+    g_signal_connect (widget, "popup_menu",
+                     G_CALLBACK (wxgtk_window_popup_menu_callback), this);
+    g_signal_connect (widget, "enter_notify_event",
+                      G_CALLBACK (gtk_window_enter_callback), this);
+    g_signal_connect (widget, "leave_notify_event",
+                      G_CALLBACK (gtk_window_leave_callback), this);
 }
 
 bool wxWindowGTK::Destroy()
@@ -2938,7 +3004,10 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
 void wxWindowGTK::OnInternalIdle()
 {
     if ( m_dirtyTabOrder )
+    {
+        m_dirtyTabOrder = false;
         RealizeTabOrder();
+    }
 
     // Update style if the window was not yet realized
     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called
@@ -3521,14 +3590,42 @@ void wxWindowGTK::RealizeTabOrder()
 {
     if (m_wxwindow)
     {
-        if (m_children.size() > 0)
+        if ( !m_children.empty() )
         {
+#if wxUSE_STATTEXT
+            // we don't only construct the correct focus chain but also use
+            // this opportunity to update the mnemonic widgets for all labels
+            //
+            // it would be nice to extract this code from here and put it in
+            // stattext.cpp to reduce dependencies but there is no really easy
+            // way to do it unfortunately
+            wxStaticText *lastLabel = NULL;
+#endif // wxUSE_STATTEXT
+
             GList *chain = NULL;
 
-            for (wxWindowList::const_iterator i = m_children.begin();
-                    i != m_children.end(); ++i)
+            for ( wxWindowList::const_iterator i = m_children.begin();
+                  i != m_children.end();
+                  ++i )
             {
-                chain = g_list_prepend(chain, (*i)->m_widget);
+                wxWindowGTK *win = *i;
+#if wxUSE_STATTEXT
+                if ( lastLabel )
+                {
+                    if ( win->AcceptsFocusFromKeyboard() )
+                    {
+                        GtkLabel *l = GTK_LABEL(lastLabel->m_widget);
+                        gtk_label_set_mnemonic_widget(l, win->m_widget);
+                        lastLabel = NULL;
+                    }
+                }
+                else // check if this one is a label
+                {
+                    lastLabel = wxDynamicCast(win, wxStaticText);
+                }
+#endif // wxUSE_STATTEXT
+
+                chain = g_list_prepend(chain, win->m_widget);
             }
 
             chain = g_list_reverse(chain);
@@ -3536,13 +3633,11 @@ void wxWindowGTK::RealizeTabOrder()
             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow), chain);
             g_list_free(chain);
         }
-        else
+        else // no children
         {
             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow));
         }
     }
-
-    m_dirtyTabOrder = false;
 }
 
 void wxWindowGTK::Raise()
@@ -3606,6 +3701,39 @@ void wxWindowGTK::WarpPointer( int x, int y )
         gdk_window_warp_pointer( window, x, y );
 }
 
+static bool wxScrollAdjust(GtkAdjustment* adj, double change)
+{
+    double value_start = adj->value;
+    double value = value_start + change;
+    double upper = adj->upper - adj->page_size;
+    if (value > upper)
+    {
+        value = upper;
+    }
+    // Lower bound will be checked by gtk_adjustment_set_value
+    gtk_adjustment_set_value(adj, value);
+    return adj->value != value_start;
+}
+
+bool wxWindowGTK::ScrollLines(int lines)
+{
+    return
+        m_vAdjust != NULL &&
+        wxScrollAdjust(m_vAdjust, lines * m_vAdjust->step_increment);
+}
+
+bool wxWindowGTK::ScrollPages(int pages)
+{
+    return
+        m_vAdjust != NULL &&
+        wxScrollAdjust(m_vAdjust, pages * m_vAdjust->page_increment);
+}
+
+void wxWindowGTK::SetVScrollAdjustment(GtkAdjustment* adj)
+{
+    wxASSERT(m_vAdjust == NULL);
+    m_vAdjust = adj;
+}
 
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
@@ -4087,21 +4215,21 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
     }
 
     if (orient == wxHORIZONTAL)
-        gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
+        g_signal_emit_by_name (m_hAdjust, "changed");
     else
-        gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
+        g_signal_emit_by_name (m_vAdjust, "changed");
 }
 
 void wxWindowGTK::GtkUpdateScrollbar(int orient)
 {
     GtkAdjustment *adj = orient == wxHORIZONTAL ? m_hAdjust : m_vAdjust;
-    GtkSignalFunc fn = orient == wxHORIZONTAL
-                        ? (GtkSignalFunc)gtk_window_hscroll_callback
-                        : (GtkSignalFunc)gtk_window_vscroll_callback;
+    gpointer fn = orient == wxHORIZONTAL
+            ? (gpointer) gtk_window_hscroll_callback
+            : (gpointer) gtk_window_vscroll_callback;
 
-    gtk_signal_disconnect_by_func(GTK_OBJECT(adj), fn, (gpointer)this);
-    gtk_signal_emit_by_name(GTK_OBJECT(adj), "value_changed");
-    gtk_signal_connect(GTK_OBJECT(adj), "value_changed", fn, (gpointer)this);
+    g_signal_handlers_disconnect_by_func (adj, fn, this);
+    g_signal_emit_by_name (adj, "value_changed");
+    g_signal_connect (adj, "value_changed", G_CALLBACK (fn), this);
 }
 
 void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )