]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
don't declare inline function with dllexport declaration, this provokes mingw32 warni...
[wxWidgets.git] / src / gtk / window.cpp
index 35aa3f62426d9ac0da5298d00912439fb458f774..bb6ec9e921f128ec893a30b27d7cfbd483ddbcc7 100644 (file)
@@ -469,8 +469,6 @@ gtk_window_expose_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     // This callback gets called in drawing-idle time under
     // GTK 2.0, so we don't need to defer anything to idle
     // time anymore.
@@ -982,8 +980,6 @@ gtk_window_key_press_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     if (!win->m_hasVMT)
         return FALSE;
     if (g_blockEventsOnDrag)
@@ -1114,30 +1110,6 @@ gtk_window_key_press_callback( GtkWidget *widget,
         }
     }
 
-    // win is a control: tab can be propagated up
-    if ( !ret &&
-         ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
-// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may
-//     have this style, yet choose not to process this particular TAB in which
-//     case TAB must still work as a navigational character
-// JS: enabling again to make consistent with other platforms
-//     (with wxTE_PROCESS_TAB you have to call Navigate to get default
-//     navigation behaviour)
-#if wxUSE_TEXTCTRL
-         (! (win->HasFlag(wxTE_PROCESS_TAB) && win->IsKindOf(CLASSINFO(wxTextCtrl)) )) &&
-#endif
-         win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
-    {
-        wxNavigationKeyEvent new_event;
-        new_event.SetEventObject( win->GetParent() );
-        // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
-        new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
-        // CTRL-TAB changes the (parent) window, i.e. switch notebook page
-        new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
-        new_event.SetCurrentFocus( win );
-        ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
-    }
-
     return ret;
 }
 }
@@ -1158,7 +1130,7 @@ gtk_wxwindow_commit_cb (GtkIMContext *context,
                                   window, window->m_imData->lastKeyEvent);
     }
 
-    const wxWxCharBuffer data(wxGTK_CONV_BACK(str));
+    const wxWxCharBuffer data(wxGTK_CONV_BACK_SYS(str));
     if( !data )
         return;
 
@@ -1224,8 +1196,6 @@ gtk_window_key_release_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     if (!win->m_hasVMT)
         return FALSE;
 
@@ -1402,8 +1372,6 @@ int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     if (!m_hasVMT)
         return FALSE;
     if (g_blockEventsOnDrag)
@@ -1469,7 +1437,7 @@ gtk_window_button_press_callback( GtkWidget *widget,
 
     g_lastButtonNumber = gdk_event->button;
 
-    if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus())
+    if (win->m_wxwindow && (g_focusWindow != win) && win->CanAcceptFocus())
     {
         gtk_widget_grab_focus( win->m_wxwindow );
     }
@@ -1683,9 +1651,9 @@ gtk_window_button_release_callback( GtkWidget *widget,
     event.SetId( win->GetId() );
 
     bool ret = win->GTKProcessEvent(event);
-    
+
     g_lastMouseEvent = NULL;
-    
+
     return ret;
 }
 
@@ -1770,8 +1738,6 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     if (gdk_event->direction != GDK_SCROLL_UP &&
         gdk_event->direction != GDK_SCROLL_DOWN)
     {
@@ -1828,8 +1794,6 @@ gtk_window_focus_in_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     if (win->m_imData)
         gtk_im_context_focus_in(win->m_imData->context);
 
@@ -1880,8 +1844,6 @@ gtk_window_focus_out_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     if (win->m_imData)
         gtk_im_context_focus_out(win->m_imData->context);
 
@@ -1904,12 +1866,14 @@ gtk_window_focus_out_callback( GtkWidget *widget,
     }
 #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 )
     {
+        // the event handler might delete the window when it loses focus, so
+        // check whether this is a custom window before calling it
+        const bool has_wxwindow = win->m_wxwindow != NULL;
+
         win->m_hasFocus = false;
 
         wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
@@ -1917,14 +1881,32 @@ gtk_window_focus_out_callback( GtkWidget *widget,
 
         (void)win->GTKProcessEvent( event );
 
-        ret = TRUE;
+        // Disable default focus handling for custom windows
+        // since the default GTK+ handler issues a repaint
+        if ( has_wxwindow )
+            return TRUE;
     }
 
-    // Disable default focus handling for custom windows
-    // since the default GTK+ handler issues a repaint
-    if (win->m_wxwindow)
-        return ret;
+    // continue with normal processing
+    return FALSE;
+}
 
+static gboolean
+wx_window_focus_callback(GtkWidget *widget,
+                         GtkDirectionType direction,
+                         wxWindowGTK *win)
+{
+    // the default handler for focus signal in GtkPizza (or, rather, in
+    // GtkScrolledWindow from which GtkPizza inherits this behaviour) sets
+    // focus to the window itself even if it doesn't accept focus, i.e. has no
+    // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing
+    // the signal from reaching gtk_scrolled_window_focus() if we don't have
+    // any children which might accept focus (we know we don't accept the focus
+    // ourselves as this signal is only connected in this case)
+    if ( win->GetChildren().empty() )
+        g_signal_stop_emission_by_name(widget, "focus");
+
+    // we didn't change the focus
     return FALSE;
 }
 
@@ -2041,8 +2023,6 @@ gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win)
 {
     DEBUG_MAIN_THREAD
 
-    // don't need to install idle handler, its done from "event" signal
-
     g_blockEventsOnScroll = true;
     win->m_mouseButtonDown = true;
 
@@ -2104,9 +2084,6 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
     if (win->m_imData)
     {
         GtkPizza *pizza = GTK_PIZZA( m_widget );
@@ -2128,25 +2105,17 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
                                GtkAllocation *alloc,
                                wxWindow *win )
 {
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
     int client_width = 0;
     int client_height = 0;
     win->GetClientSize( &client_width, &client_height );
     if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
         return;
 
-#if 0
-        wxPrintf( wxT("size_allocate ") );
-        if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-            wxPrintf( win->GetClassInfo()->GetClassName() );
-        wxPrintf( wxT(" %d %d %d %d\n"),
-                alloc->x,
-                alloc->y,
-                alloc->width,
-                alloc->height );
-#endif
+    if ( !client_width && !client_height )
+    {
+        // the window is currently unmapped, don't generate size events
+        return;
+    }
 
     win->m_oldClientWidth = client_width;
     win->m_oldClientHeight = client_height;
@@ -2192,7 +2161,7 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
     child->m_y += gtk_pizza_get_yoffset( pizza );
 
     gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
-                     GTK_WIDGET(child->m_widget),
+                     child->m_widget,
                      child->m_x,
                      child->m_y,
                      child->m_width,
@@ -2260,7 +2229,6 @@ void wxWindowGTK::Init()
 
     m_sizeSet = false;
     m_hasVMT = false;
-    m_needParent = true;
     m_isBeingDeleted = false;
 
     m_showOnIdle= false;
@@ -2288,7 +2256,6 @@ void wxWindowGTK::Init()
 
     m_insertCallback = (wxInsertChildFunction) NULL;
 
-    m_acceptsFocus = false;
     m_hasFocus = false;
 
     m_clipPaintRegion = false;
@@ -2334,66 +2301,96 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
     m_insertCallback = wxInsertChildInWindow;
 
-    m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
-    GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
-
-    GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
-
-    GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
-    scroll_class->scrollbar_spacing = 0;
 
-    if (HasFlag(wxALWAYS_SHOW_SB))
+    if (!HasFlag(wxHSCROLL) && !HasFlag(wxVSCROLL))
     {
-        gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS );
+        m_wxwindow = gtk_pizza_new_no_scroll();
 
-        scrolledWindow->hscrollbar_visible = TRUE;
-        scrolledWindow->vscrollbar_visible = TRUE;
+#ifndef __WXUNIVERSAL__
+        if (HasFlag(wxSIMPLE_BORDER))
+            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
+        else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
+            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
+#endif // __WXUNIVERSAL__
+
+        m_widget = m_wxwindow;
     }
     else
     {
-        gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
-    }
-
-    m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar);
-    m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar);
-    if (GetLayoutDirection() == wxLayout_RightToLeft)
-        gtk_range_set_inverted( m_scrollBar[ScrollDir_Horz], TRUE );
-
-    m_wxwindow = gtk_pizza_new();
+        m_wxwindow = gtk_pizza_new();
 
 #ifndef __WXUNIVERSAL__
-    if (HasFlag(wxSIMPLE_BORDER))
-        gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
-    else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
-        gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
+        if (HasFlag(wxSIMPLE_BORDER))
+            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
+        else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
+            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
 #endif // __WXUNIVERSAL__
 
-    gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
+        m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
 
-    GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
-    m_acceptsFocus = true;
+        GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
 
-    // connect various scroll-related events
-    for ( int dir = 0; dir < ScrollDir_Max; dir++ )
-    {
-        // 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
-        g_signal_connect(m_scrollBar[dir], "button_press_event",
+        GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
+        scroll_class->scrollbar_spacing = 0;
+
+        // There is a conflict with default bindings at GTK+
+        // level between scrolled windows and notebooks both of which want to use
+        // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal
+        // direction and notebooks for changing pages -- we decide that if we don't
+        // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it
+        // means we can get working keyboard navigation in notebooks
+        if ( !HasFlag(wxHSCROLL) )
+        {
+            GtkBindingSet *
+                bindings = gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget));
+            if ( bindings )
+            {
+                gtk_binding_entry_remove(bindings, GDK_Page_Up, GDK_CONTROL_MASK);
+                gtk_binding_entry_remove(bindings, GDK_Page_Down, GDK_CONTROL_MASK);
+            }
+        }
+
+        if (HasFlag(wxALWAYS_SHOW_SB))
+        {
+            gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS );
+
+            scrolledWindow->hscrollbar_visible = TRUE;
+            scrolledWindow->vscrollbar_visible = TRUE;
+        }
+        else
+        {
+            gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
+        }
+
+        m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar);
+        m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar);
+        if (GetLayoutDirection() == wxLayout_RightToLeft)
+            gtk_range_set_inverted( m_scrollBar[ScrollDir_Horz], TRUE );
+
+        gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
+
+        // connect various scroll-related events
+        for ( int dir = 0; dir < ScrollDir_Max; dir++ )
+        {
+            // 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
+            g_signal_connect(m_scrollBar[dir], "button_press_event",
                          G_CALLBACK(gtk_scrollbar_button_press_event), this);
-        g_signal_connect(m_scrollBar[dir], "button_release_event",
+            g_signal_connect(m_scrollBar[dir], "button_release_event",
                          G_CALLBACK(gtk_scrollbar_button_release_event), this);
 
-        gulong handler_id = g_signal_connect(m_scrollBar[dir], "event_after",
+            gulong handler_id = g_signal_connect(m_scrollBar[dir], "event_after",
                                 G_CALLBACK(gtk_scrollbar_event_after), this);
-        g_signal_handler_block(m_scrollBar[dir], handler_id);
+            g_signal_handler_block(m_scrollBar[dir], handler_id);
 
-        // these handlers get notified when scrollbar slider moves
-        g_signal_connect(m_scrollBar[dir], "value_changed",
+            // these handlers get notified when scrollbar slider moves
+            g_signal_connect(m_scrollBar[dir], "value_changed",
                          G_CALLBACK(gtk_scrollbar_value_changed), this);
-    }
+        }
 
-    gtk_widget_show( m_wxwindow );
+        gtk_widget_show( m_wxwindow );
+    }
 
     if (m_parent)
         m_parent->DoAddChild( this );
@@ -2439,7 +2436,7 @@ wxWindowGTK::~wxWindowGTK()
     // delete before the widgets to avoid a crash on solaris
     delete m_imData;
 
-    if (m_wxwindow)
+    if (m_wxwindow && (m_wxwindow != m_widget))
     {
         gtk_widget_destroy( m_wxwindow );
         m_wxwindow = (GtkWidget*) NULL;
@@ -2454,7 +2451,10 @@ wxWindowGTK::~wxWindowGTK()
 
 bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const wxSize &size )
 {
-    wxCHECK_MSG( !m_needParent || parent, false, wxT("Need complete parent.") );
+    if ( GTKNeedsParent() )
+    {
+        wxCHECK_MSG( parent, false, wxT("Must have non-NULL parent") );
+    }
 
     // Use either the given size, or the default if -1 is given.
     // See wxWindowBase for these functions.
@@ -2521,6 +2521,14 @@ void wxWindowGTK::PostCreation()
         }
     }
 
+    if ( !AcceptsFocusFromKeyboard() )
+    {
+        SetCanFocus(false);
+
+        g_signal_connect(m_widget, "focus",
+                            G_CALLBACK(wx_window_focus_callback), this);
+    }
+
     // connect to the various key and mouse handlers
 
     GtkWidget *connect_widget = GetConnectWidget();
@@ -2556,7 +2564,7 @@ void wxWindowGTK::PostCreation()
         // FIXME: what should be done here ?
     }
 #endif
-    else
+    else if ( !IsTopLevel() ) // top level windows use their own callback
     {
         // This is needed if we want to add our windows into native
         // GTK controls, such as the toolbar. With this callback, the
@@ -2663,7 +2671,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
     if (wxDynamicCast(GetParent(), wxToolBar))
     {
        // don't take the x,y values, they're wrong because toolbar sets them
-       GtkWidget  *widget = GTK_WIDGET(m_widget);
+       GtkWidget  *widget = m_widget;
        gtk_widget_set_size_request (widget, m_width, m_height);
     }
     else
@@ -2794,7 +2802,7 @@ void wxWindowGTK::OnInternalIdle()
            windows above so that checking for the current cursor is
            not possible. */
 
-        if (m_wxwindow)
+        if (m_wxwindow && (m_wxwindow != m_widget))
         {
             GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
             if (window)
@@ -2911,8 +2919,8 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
             int org_y = 0;
             gdk_window_get_origin( source, &org_x, &org_y );
 
-            if (GetParent())
-                GetParent()->ScreenToClient(&org_x, &org_y);
+            if (m_parent)
+                m_parent->ScreenToClient(&org_x, &org_y);
 
             wx_const_cast(wxWindowGTK*, this)->m_x = org_x;
             wx_const_cast(wxWindowGTK*, this)->m_y = org_y;
@@ -3026,40 +3034,13 @@ bool wxWindowGTK::Show( bool show )
     return true;
 }
 
-static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
-{
-    win->OnParentEnable(enable);
-
-    // Recurse, so that children have the opportunity to Do The Right Thing
-    // and reset colours that have been messed up by a parent's (really ancestor's)
-    // Enable call
-    for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
-          node;
-          node = node->GetNext() )
-    {
-        wxWindow *child = node->GetData();
-        if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
-            wxWindowNotifyEnable(child, enable);
-    }
-}
-
-bool wxWindowGTK::Enable( bool enable )
+void wxWindowGTK::DoEnable( bool enable )
 {
-    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
-
-    if (!wxWindowBase::Enable(enable))
-    {
-        // nothing to do
-        return false;
-    }
+    wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
     gtk_widget_set_sensitive( m_widget, enable );
-    if ( m_wxwindow )
+    if (m_wxwindow && (m_wxwindow != m_widget))
         gtk_widget_set_sensitive( m_wxwindow, enable );
-
-    wxWindowNotifyEnable(this, enable);
-
-    return true;
 }
 
 int wxWindowGTK::GetCharHeight() const
@@ -3250,9 +3231,20 @@ void wxWindowGTK::SetFocus()
     }
 }
 
-bool wxWindowGTK::AcceptsFocus() const
+void wxWindowGTK::SetCanFocus(bool canFocus)
 {
-    return m_acceptsFocus && wxWindowBase::AcceptsFocus();
+    if ( canFocus )
+        GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS);
+    else
+        GTK_WIDGET_UNSET_FLAGS(m_widget, GTK_CAN_FOCUS);
+
+    if ( m_wxwindow && (m_widget != m_wxwindow) )
+    {
+        if ( canFocus )
+            GTK_WIDGET_SET_FLAGS(m_wxwindow, GTK_CAN_FOCUS);
+        else
+            GTK_WIDGET_UNSET_FLAGS(m_wxwindow, GTK_CAN_FOCUS);
+    }
 }
 
 bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
@@ -3318,22 +3310,20 @@ void wxWindowGTK::AddChild(wxWindowBase *child)
 {
     wxWindowBase::AddChild(child);
     m_dirtyTabOrder = true;
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    wxTheApp->WakeUpIdle();
 }
 
 void wxWindowGTK::RemoveChild(wxWindowBase *child)
 {
     wxWindowBase::RemoveChild(child);
     m_dirtyTabOrder = true;
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    wxTheApp->WakeUpIdle();
 }
 
 /* static */
 wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget)
 {
-    return gtk_widget_get_direction(GTK_WIDGET(widget)) == GTK_TEXT_DIR_RTL
+    return gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL
                 ? wxLayout_RightToLeft
                 : wxLayout_LeftToRight;
 }
@@ -3343,7 +3333,7 @@ void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir)
 {
     wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") );
 
-    gtk_widget_set_direction(GTK_WIDGET(widget),
+    gtk_widget_set_direction(widget,
                              dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL
                                                          : GTK_TEXT_DIR_LTR);
 }
@@ -3374,7 +3364,7 @@ void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir)
 
     GTKSetLayout(m_widget, dir);
 
-    if (m_wxwindow)
+    if (m_wxwindow && (m_wxwindow != m_widget))
         GTKSetLayout(m_wxwindow, dir);
 }
 
@@ -3391,8 +3381,31 @@ void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
 {
     wxWindowBase::DoMoveInTabOrder(win, move);
     m_dirtyTabOrder = true;
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    wxTheApp->WakeUpIdle();
+}
+
+bool wxWindowGTK::DoNavigateIn(int flags)
+{
+    if ( flags & wxNavigationKeyEvent::WinChange )
+    {
+        wxFAIL_MSG( _T("not implemented") );
+
+        return false;
+    }
+    else // navigate inside the container
+    {
+        wxWindow *parent = wxGetTopLevelParent(this);
+        wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") );
+
+        GtkDirectionType dir;
+        dir = flags & wxNavigationKeyEvent::IsForward ? GTK_DIR_TAB_FORWARD
+                                                      : GTK_DIR_TAB_BACKWARD;
+
+        gboolean rc;
+        g_signal_emit_by_name(parent->m_widget, "focus", dir, &rc);
+
+        return rc == TRUE;
+    }
 }
 
 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const
@@ -3642,7 +3655,7 @@ void wxWindowGTK::GtkUpdate()
 {
     if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
         gdk_window_process_updates( GTK_PIZZA(m_wxwindow)->bin_window, FALSE );
-    if (m_widget && m_widget->window)
+    if (m_widget && m_widget->window && (m_wxwindow != m_widget))
         gdk_window_process_updates( m_widget->window, FALSE );
 
     // for consistency with other platforms (and also because it's convenient
@@ -3874,45 +3887,54 @@ GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
             pango_font_description_copy( m_font.GetNativeFontInfo()->description );
     }
 
+    int flagsNormal = 0,
+        flagsPrelight = 0,
+        flagsActive = 0,
+        flagsInsensitive = 0;
+
     if ( m_foregroundColour.Ok() )
     {
         const GdkColor *fg = m_foregroundColour.GetColor();
 
-        style->fg[GTK_STATE_NORMAL] = *fg;
-        style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG;
+        style->fg[GTK_STATE_NORMAL] =
+        style->text[GTK_STATE_NORMAL] = *fg;
+        flagsNormal |= GTK_RC_FG | GTK_RC_TEXT;
 
-        style->fg[GTK_STATE_PRELIGHT] = *fg;
-        style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG;
+        style->fg[GTK_STATE_PRELIGHT] =
+        style->text[GTK_STATE_PRELIGHT] = *fg;
+        flagsPrelight |= GTK_RC_FG | GTK_RC_TEXT;
 
-        style->fg[GTK_STATE_ACTIVE] = *fg;
-        style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG;
+        style->fg[GTK_STATE_ACTIVE] =
+        style->text[GTK_STATE_ACTIVE] = *fg;
+        flagsActive |= GTK_RC_FG | GTK_RC_TEXT;
     }
 
     if ( m_backgroundColour.Ok() )
     {
         const GdkColor *bg = m_backgroundColour.GetColor();
 
-        style->bg[GTK_STATE_NORMAL] = *bg;
+        style->bg[GTK_STATE_NORMAL] =
         style->base[GTK_STATE_NORMAL] = *bg;
-        style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags)
-            (style->color_flags[GTK_STATE_NORMAL] | GTK_RC_BG | GTK_RC_BASE);
+        flagsNormal |= GTK_RC_BG | GTK_RC_BASE;
 
-        style->bg[GTK_STATE_PRELIGHT] = *bg;
+        style->bg[GTK_STATE_PRELIGHT] =
         style->base[GTK_STATE_PRELIGHT] = *bg;
-        style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags)
-            (style->color_flags[GTK_STATE_PRELIGHT] | GTK_RC_BG | GTK_RC_BASE);
+        flagsPrelight |= GTK_RC_BG | GTK_RC_BASE;
 
-        style->bg[GTK_STATE_ACTIVE] = *bg;
+        style->bg[GTK_STATE_ACTIVE] =
         style->base[GTK_STATE_ACTIVE] = *bg;
-        style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags)
-            (style->color_flags[GTK_STATE_ACTIVE] | GTK_RC_BG | GTK_RC_BASE);
+        flagsActive |= GTK_RC_BG | GTK_RC_BASE;
 
-        style->bg[GTK_STATE_INSENSITIVE] = *bg;
+        style->bg[GTK_STATE_INSENSITIVE] =
         style->base[GTK_STATE_INSENSITIVE] = *bg;
-        style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags)
-            (style->color_flags[GTK_STATE_INSENSITIVE] | GTK_RC_BG | GTK_RC_BASE);
+        flagsInsensitive |= GTK_RC_BG | GTK_RC_BASE;
     }
 
+    style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags)flagsNormal;
+    style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags)flagsPrelight;
+    style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags)flagsActive;
+    style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags)flagsInsensitive;
+
     return style;
 }
 
@@ -4109,6 +4131,7 @@ void wxWindowGTK::SetScrollbar(int orient,
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
+    wxCHECK_RET( m_wxwindow != m_widget, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
 
     if (range > 0)
     {
@@ -4138,6 +4161,7 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
+    wxCHECK_RET( m_wxwindow != m_widget, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
 
     // This check is more than an optimization. Without it, the slider
     //   will not move smoothly while tracking when using wxScrollHelper.
@@ -4164,6 +4188,7 @@ int wxWindowGTK::GetScrollThumb(int orient) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
     wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
+    wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
 
     return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size);
 }
@@ -4172,6 +4197,7 @@ int wxWindowGTK::GetScrollPos( int orient ) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
     wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
+    wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
 
     return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5);
 }
@@ -4180,6 +4206,7 @@ int wxWindowGTK::GetScrollRange( int orient ) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
     wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
+    wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
 
     return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper);
 }
@@ -4197,9 +4224,6 @@ wxEventType wxWindowGTK::GetScrollEventType(GtkRange* range)
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
     wxASSERT(range == m_scrollBar[0] || range == m_scrollBar[1]);
 
     const int barIndex = range == m_scrollBar[1];