]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Generate wxPropertyGrid splitter (column divider) events: wxEVT_PG_COL_BEGIN_DRAG...
[wxWidgets.git] / src / gtk / window.cpp
index e88df950cb25335ed2d23d2718402b09eb0ee4cf..759ebc9afe77e9ac6e06937059bbaa3beca5915c 100644 (file)
@@ -1,6 +1,6 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        src/gtk/window.cpp
-// Purpose:
+// Purpose:     wxWindowGTK implementation
 // Author:      Robert Roebling
 // Id:          $Id$
 // Copyright:   (c) 1998 Robert Roebling, Julian Smart
@@ -228,7 +228,7 @@ int          g_lastButtonNumber = 0;
 //-----------------------------------------------------------------------------
 
 // the trace mask used for the focus debugging messages
-#define TRACE_FOCUS _T("focus")
+#define TRACE_FOCUS wxT("focus")
 
 //-----------------------------------------------------------------------------
 // missing gdk functions
@@ -383,7 +383,7 @@ inline bool wxIsUpperChar(int code)
 
 
 // set WXTRACE to this to see the key event codes on the console
-#define TRACE_KEYS  _T("keyevent")
+#define TRACE_KEYS  wxT("keyevent")
 
 // translates an X key symbol to WXK_XXX value
 //
@@ -683,7 +683,6 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
     event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0;
-    event.m_scanCode = gdk_event->keyval;
     event.m_rawCode = (wxUint32) gdk_event->keyval;
     event.m_rawFlags = 0;
 #if wxUSE_UNICODE
@@ -715,9 +714,9 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
 
     KeySym keysym = gdk_event->keyval;
 
-    wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %ld"),
-               event.GetEventType() == wxEVT_KEY_UP ? _T("release")
-                                                    : _T("press"),
+    wxLogTrace(TRACE_KEYS, wxT("Key %s event: keysym = %ld"),
+               event.GetEventType() == wxEVT_KEY_UP ? wxT("release")
+                                                    : wxT("press"),
                keysym);
 
     long key_code = wxTranslateKeySymToWXKey(keysym, false /* !isChar */);
@@ -746,7 +745,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
             Display *dpy = (Display *)wxGetDisplay();
             KeyCode keycode = XKeysymToKeycode(dpy, keysym);
 
-            wxLogTrace(TRACE_KEYS, _T("\t-> keycode %d"), keycode);
+            wxLogTrace(TRACE_KEYS, wxT("\t-> keycode %d"), keycode);
 
             KeySym keysymNormalized = XKeycodeToKeysym(dpy, keycode, 0);
 
@@ -785,7 +784,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
         }
     }
 
-    wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %ld"), key_code);
+    wxLogTrace(TRACE_KEYS, wxT("\t-> wxKeyCode %ld"), key_code);
 
     // sending unknown key events doesn't really make sense
     if ( !key_code )
@@ -858,7 +857,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
         win->m_imData->lastKeyEvent = NULL;
         if (intercepted_by_IM)
         {
-            wxLogTrace(TRACE_KEYS, _T("Key event intercepted by IM"));
+            wxLogTrace(TRACE_KEYS, wxT("Key event intercepted by IM"));
             return TRUE;
         }
     }
@@ -920,7 +919,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
 
         if ( key_code )
         {
-            wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
+            wxLogTrace(TRACE_KEYS, wxT("Char event: %ld"), key_code);
 
             event.m_keyCode = key_code;
 
@@ -997,7 +996,7 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context),
         event.m_uniChar = *pstr;
         // Backward compatible for ISO-8859-1
         event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0;
-        wxLogTrace(TRACE_KEYS, _T("IM sent character '%c'"), event.m_uniChar);
+        wxLogTrace(TRACE_KEYS, wxT("IM sent character '%c'"), event.m_uniChar);
 #else
         event.m_keyCode = (char)*pstr;
 #endif  // wxUSE_UNICODE
@@ -1075,15 +1074,15 @@ template<typename T> void InitMouseEvent(wxWindowGTK *win,
                                          T *gdk_event)
 {
     event.SetTimestamp( gdk_event->time );
-    event.m_shiftDown = gdk_event->state & GDK_SHIFT_MASK;
-    event.m_controlDown = gdk_event->state & GDK_CONTROL_MASK;
-    event.m_altDown = gdk_event->state & GDK_MOD1_MASK;
-    event.m_metaDown = gdk_event->state & GDK_META_MASK;
-    event.m_leftDown = gdk_event->state & GDK_BUTTON1_MASK;
-    event.m_middleDown = gdk_event->state & GDK_BUTTON2_MASK;
-    event.m_rightDown = gdk_event->state & GDK_BUTTON3_MASK;
-    event.m_aux1Down = gdk_event->state & GDK_BUTTON4_MASK;
-    event.m_aux2Down = gdk_event->state & GDK_BUTTON5_MASK;
+    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0;
+    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
+    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
+    event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0;
+    event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK) != 0;
+    event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK) != 0;
+    event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK) != 0;
+    event.m_aux1Down = (gdk_event->state & GDK_BUTTON4_MASK) != 0;
+    event.m_aux2Down = (gdk_event->state & GDK_BUTTON5_MASK) != 0;
 
     wxPoint pt = win->GetClientAreaOrigin();
     event.m_x = (wxCoord)gdk_event->x - pt.x;
@@ -1209,6 +1208,11 @@ bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const
     return HandleWindowEvent(event);
 }
 
+bool wxWindowGTK::GTKShouldIgnoreEvent() const
+{
+    return !m_hasVMT || g_blockEventsOnDrag;
+}
+
 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
 {
     if (!m_hasVMT)
@@ -1921,30 +1925,6 @@ void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget),
 
 } // extern "C"
 
-// Helper to suspend colour change event event processing while we change a widget's style
-class wxSuspendStyleEvents
-{
-public:
-    wxSuspendStyleEvents(wxWindow* win)
-    {
-        m_win = NULL;
-        if (win->m_wxwindow && win->IsTopLevel())
-        {
-            m_win = win;
-            g_signal_handlers_block_by_func(
-                m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win);
-        }
-    }
-    ~wxSuspendStyleEvents()
-    {
-        if (m_win)
-            g_signal_handlers_unblock_by_func(
-                m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win);
-    }
-
-    wxWindow* m_win;
-};
-
 // ----------------------------------------------------------------------------
 // this wxWindowBase function is implemented here (in platform-specific file)
 // because it is static and so couldn't be made virtual
@@ -1959,8 +1939,10 @@ wxWindow *wxWindowBase::DoFindFocus()
 
 void wxWindowGTK::AddChildGTK(wxWindowGTK* child)
 {
-    /* the window might have been scrolled already, do we
-       have to adapt the position */
+    wxASSERT_MSG(m_wxwindow, "Cannot add a child to a window without a client area");
+
+    // the window might have been scrolled already, we
+    // have to adapt the position
     wxPizza* pizza = WX_PIZZA(m_wxwindow);
     child->m_x += pizza->m_scroll_x;
     child->m_y += pizza->m_scroll_y;
@@ -1993,16 +1975,16 @@ wxMouseState wxGetMouseState()
 
     ms.SetX(x);
     ms.SetY(y);
-    ms.SetLeftDown(mask & GDK_BUTTON1_MASK);
-    ms.SetMiddleDown(mask & GDK_BUTTON2_MASK);
-    ms.SetRightDown(mask & GDK_BUTTON3_MASK);
-    ms.SetAux1Down(mask & GDK_BUTTON4_MASK);
-    ms.SetAux2Down(mask & GDK_BUTTON5_MASK);
+    ms.SetLeftDown((mask & GDK_BUTTON1_MASK) != 0);
+    ms.SetMiddleDown((mask & GDK_BUTTON2_MASK) != 0);
+    ms.SetRightDown((mask & GDK_BUTTON3_MASK) != 0);
+    ms.SetAux1Down((mask & GDK_BUTTON4_MASK) != 0);
+    ms.SetAux2Down((mask & GDK_BUTTON5_MASK) != 0);
 
-    ms.SetControlDown(mask & GDK_CONTROL_MASK);
-    ms.SetShiftDown(mask & GDK_SHIFT_MASK);
-    ms.SetAltDown(mask & GDK_MOD1_MASK);
-    ms.SetMetaDown(mask & GDK_META_MASK);
+    ms.SetControlDown((mask & GDK_CONTROL_MASK) != 0);
+    ms.SetShiftDown((mask & GDK_SHIFT_MASK) != 0);
+    ms.SetAltDown((mask & GDK_MOD1_MASK) != 0);
+    ms.SetMetaDown((mask & GDK_META_MASK) != 0);
 
     return ms;
 }
@@ -2106,7 +2088,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
 #endif
 
 
-    m_wxwindow = wxPizza::New(m_windowStyle,this);
+    m_wxwindow = wxPizza::New(m_windowStyle);
 #ifndef __WXUNIVERSAL__
     if (HasFlag(wxPizza::BORDER_STYLES))
     {
@@ -2335,40 +2317,25 @@ void wxWindowGTK::PostCreation()
             G_CALLBACK(size_allocate), this);
     }
 
-    if (m_wxwindow)
-    {
 #if GTK_CHECK_VERSION(2, 8, 0)
-        if (!gtk_check_version(2,8,0))
+    if ( gtk_check_version(2,8,0) == NULL )
+    {
+        // Make sure we can notify the app when mouse capture is lost
+        if ( m_wxwindow )
         {
-            // Make sure we can notify the app when mouse capture is lost
             g_signal_connect (m_wxwindow, "grab_broken_event",
                           G_CALLBACK (gtk_window_grab_broken), this);
         }
-#endif
-    }
 
-    if ( connect_widget != m_wxwindow )
-    {
-#if GTK_CHECK_VERSION(2, 8, 0)
-        if (!gtk_check_version(2,8,0))
+        if ( connect_widget != m_wxwindow )
         {
-            // Make sure we can notify app code when mouse capture is lost
             g_signal_connect (connect_widget, "grab_broken_event",
                         G_CALLBACK (gtk_window_grab_broken), this);
         }
-#endif
     }
+#endif // GTK+ >= 2.8
 
-#ifdef GTK_IS_FILE_CHOOSER_BUTTON
-    if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
-    {
-        // If we connect to the "size_request" signal of a GtkFileChooserButton
-        // then that control won't be sized properly when placed inside sizers
-        // (this can be tested removing this elseif and running XRC or WIDGETS samples)
-        // FIXME: what should be done here ?
-    } else
-#endif
-    if ( !IsTopLevel() ) // top level windows use their own callback
+    if ( GTKShouldConnectSizeRequest() )
     {
         // This is needed if we want to add our windows into native
         // GTK controls, such as the toolbar. With this callback, the
@@ -2391,6 +2358,11 @@ void wxWindowGTK::PostCreation()
         gtk_widget_show( m_widget );
 }
 
+gulong wxWindowGTK::GTKConnectWidget(const char *signal, void (*callback)())
+{
+    return g_signal_connect(m_widget, signal, callback, this);
+}
+
 void wxWindowGTK::ConnectWidget( GtkWidget *widget )
 {
     g_signal_connect (widget, "key_press_event",
@@ -2437,7 +2409,10 @@ bool wxWindowGTK::Destroy()
 void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
 {
     gtk_widget_set_size_request(m_widget, width, height);
+
     // inform the parent to perform the move
+    wxASSERT_MSG(m_parent && m_parent->m_wxwindow,
+                 "the parent window has no client area?");
     WX_PIZZA(m_parent->m_wxwindow)->move(m_widget, x, y);
 }
 
@@ -2533,7 +2508,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
             event.SetEventObject( this );
             HandleWindowEvent( event );
         }
-    } else 
+    } else
     if (sizeFlags & wxSIZE_FORCE_EVENT)
     {
         wxSizeEvent event( wxSize(m_width,m_height), GetId() );
@@ -2577,8 +2552,8 @@ void wxWindowGTK::OnInternalIdle()
         RealizeTabOrder();
     }
 
-    // Update style if the window was not yet realized
-    // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called
+    // Update style if the window was not yet realized when
+    // SetBackgroundStyle() was called
     if (m_needsStyleChange)
     {
         SetBackgroundStyle(GetBackgroundStyle());
@@ -2820,29 +2795,40 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
 
 bool wxWindowGTK::Show( bool show )
 {
-    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
-
-    if (!wxWindowBase::Show(show))
+    if ( !wxWindowBase::Show(show) )
     {
         // nothing to do
         return false;
     }
 
-    if (show && m_showOnIdle)
+    // notice that we may call Hide() before the window is created and this is
+    // actually useful to create it hidden initially -- but we can't call
+    // Show() before it is created
+    if ( !m_widget )
     {
-        // deferred
+        wxASSERT_MSG( !show, "can't show invalid window" );
+        return true;
     }
-    else
+
+    if ( show )
     {
-        if (show)
-            gtk_widget_show(m_widget);
-        else
-            gtk_widget_hide(m_widget);
-        wxShowEvent eventShow(GetId(), show);
-        eventShow.SetEventObject(this);
-        HandleWindowEvent(eventShow);
+        if ( m_showOnIdle )
+        {
+            // defer until later
+            return true;
+        }
+
+        gtk_widget_show(m_widget);
+    }
+    else // hide
+    {
+        gtk_widget_hide(m_widget);
     }
 
+    wxShowEvent eventShow(GetId(), show);
+    eventShow.SetEventObject(this);
+    HandleWindowEvent(eventShow);
+
     return true;
 }
 
@@ -2907,12 +2893,12 @@ int wxWindowGTK::GetCharWidth() const
     return (int) PANGO_PIXELS(rect.width);
 }
 
-void wxWindowGTK::GetTextExtent( const wxString& string,
-                                 int *x,
-                                 int *y,
-                                 int *descent,
-                                 int *externalLeading,
-                                 const wxFont *theFont ) const
+void wxWindowGTK::DoGetTextExtent( const wxString& string,
+                                   int *x,
+                                   int *y,
+                                   int *descent,
+                                   int *externalLeading,
+                                   const wxFont *theFont ) const
 {
     wxFont fontToUse = theFont ? *theFont : GetFont();
 
@@ -3150,14 +3136,14 @@ void wxWindowGTK::SetFocus()
          !GTK_WIDGET_CAN_FOCUS(widget) )
     {
         wxLogTrace(TRACE_FOCUS,
-                   _T("Setting focus to a child of %s(%p, %s)"),
+                   wxT("Setting focus to a child of %s(%p, %s)"),
                    GetClassInfo()->GetClassName(), this, GetLabel().c_str());
         gtk_widget_child_focus(widget, GTK_DIR_TAB_FORWARD);
     }
     else
     {
         wxLogTrace(TRACE_FOCUS,
-                   _T("Setting focus to %s(%p, %s)"),
+                   wxT("Setting focus to %s(%p, %s)"),
                    GetClassInfo()->GetClassName(), this, GetLabel().c_str());
         gtk_widget_grab_focus(widget);
     }
@@ -3251,7 +3237,7 @@ wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget)
 /* static */
 void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir)
 {
-    wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") );
+    wxASSERT_MSG( dir != wxLayout_Default, wxT("invalid layout direction") );
 
     gtk_widget_set_direction(widget,
                              dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL
@@ -3308,14 +3294,14 @@ bool wxWindowGTK::DoNavigateIn(int flags)
 {
     if ( flags & wxNavigationKeyEvent::WinChange )
     {
-        wxFAIL_MSG( _T("not implemented") );
+        wxFAIL_MSG( wxT("not implemented") );
 
         return false;
     }
     else // navigate inside the container
     {
         wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
-        wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") );
+        wxCHECK_MSG( parent, false, wxT("every window must have a TLW parent") );
 
         GtkDirectionType dir;
         dir = flags & wxNavigationKeyEvent::IsForward ? GTK_DIR_TAB_FORWARD
@@ -3457,7 +3443,7 @@ void wxWindowGTK::GTKUpdateCursor()
                 GdkWindow *win = windowsThis[n];
                 if ( !win )
                 {
-                    wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?"));
+                    wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?"));
                     continue;
                 }
 
@@ -3493,7 +3479,7 @@ wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const
             return (ScrollDir)dir;
     }
 
-    wxFAIL_MSG( _T("event from unknown scrollbar received") );
+    wxFAIL_MSG( wxT("event from unknown scrollbar received") );
 
     return ScrollDir_Max;
 }
@@ -3530,35 +3516,42 @@ bool wxWindowGTK::ScrollPages(int pages)
 void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
                           const wxRect *rect)
 {
-    GtkWidget* widget;
-    if (m_wxwindow)
-        widget = m_wxwindow;
-    else if (m_widget)
-        widget = m_widget;
-    else
-        return;
-
-    if (!widget->window)
+    if ( !m_widget )
+    {
+        // it is valid to call Refresh() for a window which hasn't been created
+        // yet, it simply doesn't do anything in this case
         return;
+    }
 
-    if (rect == NULL)
-        gtk_widget_queue_draw(widget);
+    if (!m_wxwindow)
+    {
+        if (rect)
+            gtk_widget_queue_draw_area( m_widget, rect->x, rect->y, rect->width, rect->height );
+        else
+            gtk_widget_queue_draw( m_widget );
+    }
     else
     {
-        int x = rect->x;
-        if (GetLayoutDirection() == wxLayout_RightToLeft)
-            x = GetClientSize().x - x - rect->width;
+        // Just return if the widget or one of its ancestors isn't mapped
+        GtkWidget *w;
+        for (w = m_wxwindow; w != NULL; w = w->parent)
+            if (!GTK_WIDGET_MAPPED (w))
+                return;
 
-#if 0
-        gtk_widget_queue_draw_area(widget, x, rect->y, rect->width, rect->height);
-#else
-        GdkRectangle r;
-        r.x = rect->x;
-        r.y = rect->y;
-        r.width = rect->width;
-        r.height = rect->height;
-        gdk_window_invalidate_rect( m_wxwindow->window, &r, TRUE );
-#endif
+        if (rect)
+        {
+            int x = rect->x;
+            if (GetLayoutDirection() == wxLayout_RightToLeft)
+                x = GetClientSize().x - x - rect->width;
+            GdkRectangle r;
+            r.x = rect->x;
+            r.y = rect->y;
+            r.width = rect->width;
+            r.height = rect->height;
+            gdk_window_invalidate_rect( m_wxwindow->window, &r, TRUE );
+        }
+        else
+            gdk_window_invalidate_rect( m_wxwindow->window, NULL, TRUE );
     }
 }
 
@@ -3571,7 +3564,7 @@ void wxWindowGTK::Update()
         // This ensures nothing will overwrite the drawing we are about to do.
         gdk_display_sync(display);
 
-        gdk_window_process_updates(m_widget->window, true);
+        gdk_window_process_updates(m_widget->window, TRUE);
 
         // Flush again, but no need to wait for it to finish
         gdk_display_flush(display);
@@ -3628,54 +3621,74 @@ void wxWindowGTK::GtkSendPaintEvents()
         }
     }
 
-    if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM))
+    switch ( GetBackgroundStyle() )
     {
-        // find ancestor from which to steal background
-        wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
-        if (!parent)
-            parent = (wxWindow*)this;
-
-        if (GTK_WIDGET_MAPPED(parent->m_widget))
-        {
-            wxRegionIterator upd( m_nativeUpdateRegion );
-            while (upd)
+        case wxBG_STYLE_ERASE:
             {
-                GdkRectangle rect;
-                rect.x = upd.GetX();
-                rect.y = upd.GetY();
-                rect.width = upd.GetWidth();
-                rect.height = upd.GetHeight();
-
-                gtk_paint_flat_box( parent->m_widget->style,
-                            m_wxwindow->window,
-                            (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
-                            GTK_SHADOW_NONE,
-                            &rect,
-                            parent->m_widget,
-                            (char *)"base",
-                            0, 0, -1, -1 );
-
-                ++upd;
+                wxWindowDC dc( (wxWindow*)this );
+                dc.SetDeviceClippingRegion( m_updateRegion );
+
+                // Work around gtk-qt <= 0.60 bug whereby the window colour
+                // remains grey
+                if ( UseBgCol() &&
+                        wxSystemOptions::
+                            GetOptionInt("gtk.window.force-background-colour") )
+                {
+                    dc.SetBackground(GetBackgroundColour());
+                    dc.Clear();
+                }
+
+                wxEraseEvent erase_event( GetId(), &dc );
+                erase_event.SetEventObject( this );
+
+                if ( HandleWindowEvent(erase_event) )
+                {
+                    // background erased, don't do it again
+                    break;
+                }
             }
-        }
-    }
-    else
-    {
-        wxWindowDC dc( (wxWindow*)this );
-        dc.SetDeviceClippingRegion( m_updateRegion );
+            // fall through
 
-        // Work around gtk-qt <= 0.60 bug whereby the window colour
-        // remains grey
-        if (GetBackgroundStyle() == wxBG_STYLE_COLOUR && GetBackgroundColour().Ok() && wxSystemOptions::GetOptionInt(wxT("gtk.window.force-background-colour")) == 1)
-        {
-            dc.SetBackground(wxBrush(GetBackgroundColour()));
-            dc.Clear();
-        }
+        case wxBG_STYLE_SYSTEM:
+            if ( GetThemeEnabled() )
+            {
+                // find ancestor from which to steal background
+                wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
+                if (!parent)
+                    parent = (wxWindow*)this;
+
+                if (GTK_WIDGET_MAPPED(parent->m_widget))
+                {
+                    wxRegionIterator upd( m_nativeUpdateRegion );
+                    while (upd)
+                    {
+                        GdkRectangle rect;
+                        rect.x = upd.GetX();
+                        rect.y = upd.GetY();
+                        rect.width = upd.GetWidth();
+                        rect.height = upd.GetHeight();
+
+                        gtk_paint_flat_box( parent->m_widget->style,
+                                    m_wxwindow->window,
+                                    (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
+                                    GTK_SHADOW_NONE,
+                                    &rect,
+                                    parent->m_widget,
+                                    (char *)"base",
+                                    0, 0, -1, -1 );
+
+                        ++upd;
+                    }
+                }
+            }
+            break;
 
-        wxEraseEvent erase_event( GetId(), &dc );
-        erase_event.SetEventObject( this );
+        case wxBG_STYLE_PAINT:
+            // nothing to do: window will be painted over in EVT_PAINT
+            break;
 
-        HandleWindowEvent(erase_event);
+        default:
+            wxFAIL_MSG( "unsupported background style" );
     }
 
     wxNcPaintEvent nc_paint_event( GetId() );
@@ -3716,7 +3729,21 @@ void wxWindowGTK::DoSetToolTip( wxToolTip *tip )
     wxWindowBase::DoSetToolTip(tip);
 
     if (m_tooltip)
+    {
         m_tooltip->GTKApply( (wxWindow *)this );
+    }
+    else
+    {
+        GtkWidget *w = GetConnectWidget();
+        wxToolTip::GTKApply(w, NULL);
+#if GTK_CHECK_VERSION(2, 12, 0)
+        // Just applying NULL doesn't work on 2.12.0, so also use
+        // gtk_widget_set_has_tooltip. It is part of the new GtkTooltip API
+        // but seems also to work with the old GtkTooltips.
+        if (gtk_check_version(2, 12, 0) == NULL)
+            gtk_widget_set_has_tooltip(w, FALSE);
+#endif
+    }
 }
 
 void wxWindowGTK::GTKApplyToolTip( GtkTooltips *tips, const gchar *tip )
@@ -3740,8 +3767,7 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
 
     // apply style change (forceStyle=true so that new style is applied
     // even if the bg colour changed from valid to wxNullColour)
-    if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM)
-        ApplyWidgetStyle(true);
+    GTKApplyWidgetStyle(true);
 
     return true;
 }
@@ -3763,17 +3789,17 @@ bool wxWindowGTK::SetForegroundColour( const wxColour &colour )
 
     // apply style change (forceStyle=true so that new style is applied
     // even if the bg colour changed from valid to wxNullColour):
-    ApplyWidgetStyle(true);
+    GTKApplyWidgetStyle(true);
 
     return true;
 }
 
-PangoContext *wxWindowGTK::GtkGetPangoDefaultContext()
+PangoContext *wxWindowGTK::GTKGetPangoDefaultContext()
 {
     return gtk_widget_get_pango_context( m_widget );
 }
 
-GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
+GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle)
 {
     // do we need to apply any changes at all?
     if ( !forceStyle &&
@@ -3842,9 +3868,9 @@ GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
     return style;
 }
 
-void wxWindowGTK::ApplyWidgetStyle(bool forceStyle)
+void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle)
 {
-    GtkRcStyle *style = CreateWidgetStyle(forceStyle);
+    GtkRcStyle *style = GTKCreateWidgetStyle(forceStyle);
     if ( style )
     {
         DoApplyWidgetStyle(style);
@@ -3857,19 +3883,37 @@ void wxWindowGTK::ApplyWidgetStyle(bool forceStyle)
 
 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style)
 {
-    wxSuspendStyleEvents s(static_cast<wxWindow*>(this));
+    if ( m_wxwindow )
+    {
+        // block the signal temporarily to avoid sending
+        // wxSysColourChangedEvents when we change the colours ourselves
+        bool unblock = false;
+        if ( IsTopLevel() )
+        {
+            unblock = true;
+            g_signal_handlers_block_by_func(
+                m_wxwindow, (void *)gtk_window_style_set_callback, this);
+        }
 
-    if (m_wxwindow)
         gtk_widget_modify_style(m_wxwindow, style);
+
+        if ( unblock )
+        {
+            g_signal_handlers_unblock_by_func(
+                m_wxwindow, (void *)gtk_window_style_set_callback, this);
+        }
+    }
     else
+    {
         gtk_widget_modify_style(m_widget, style);
+    }
 }
 
 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 {
     wxWindowBase::SetBackgroundStyle(style);
 
-    if (style == wxBG_STYLE_CUSTOM)
+    if ( style == wxBG_STYLE_PAINT )
     {
         GdkWindow *window;
         if ( m_wxwindow )
@@ -3905,8 +3949,9 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
     {
         // apply style change (forceStyle=true so that new style is applied
         // even if the bg colour changed from valid to wxNullColour):
-        ApplyWidgetStyle(true);
+        GTKApplyWidgetStyle(true);
     }
+
     return true;
 }
 
@@ -4051,7 +4096,7 @@ bool wxWindowGTK::SetFont( const wxFont &font )
 
     // apply style change (forceStyle=true so that new style is applied
     // even if the font changed from valid to wxNullFont):
-    ApplyWidgetStyle(true);
+    GTKApplyWidgetStyle(true);
 
     return true;
 }
@@ -4066,7 +4111,7 @@ void wxWindowGTK::DoCaptureMouse()
     else
         window = GetConnectWidget()->window;
 
-    wxCHECK_RET( window, _T("CaptureMouse() failed") );
+    wxCHECK_RET( window, wxT("CaptureMouse() failed") );
 
     const wxCursor* cursor = &m_cursor;
     if (!cursor->Ok())
@@ -4132,7 +4177,7 @@ void wxWindowGTK::SetScrollbar(int orient,
 {
     const int dir = ScrollDirFromOrient(orient);
     GtkRange* const sb = m_scrollBar[dir];
-    wxCHECK_RET( sb, _T("this window is not scrollable") );
+    wxCHECK_RET( sb, wxT("this window is not scrollable") );
 
     if (range <= 0)
     {
@@ -4161,7 +4206,7 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 {
     const int dir = ScrollDirFromOrient(orient);
     GtkRange * const sb = m_scrollBar[dir];
-    wxCHECK_RET( sb, _T("this window is not scrollable") );
+    wxCHECK_RET( sb, wxT("this window is not scrollable") );
 
     // This check is more than an optimization. Without it, the slider
     //   will not move smoothly while tracking when using wxScrollHelper.
@@ -4181,7 +4226,7 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 int wxWindowGTK::GetScrollThumb(int orient) const
 {
     GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
-    wxCHECK_MSG( sb, 0, _T("this window is not scrollable") );
+    wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") );
 
     return wxRound(sb->adjustment->page_size);
 }
@@ -4189,7 +4234,7 @@ int wxWindowGTK::GetScrollThumb(int orient) const
 int wxWindowGTK::GetScrollPos( int orient ) const
 {
     GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
-    wxCHECK_MSG( sb, 0, _T("this window is not scrollable") );
+    wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") );
 
     return wxRound(sb->adjustment->value);
 }
@@ -4197,7 +4242,7 @@ int wxWindowGTK::GetScrollPos( int orient ) const
 int wxWindowGTK::GetScrollRange( int orient ) const
 {
     GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
-    wxCHECK_MSG( sb, 0, _T("this window is not scrollable") );
+    wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") );
 
     return wxRound(sb->adjustment->upper);
 }
@@ -4292,7 +4337,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 #endif // wxUSE_CARET
 }
 
-void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
+void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
 {
     //RN: Note that static controls usually have no border on gtk, so maybe
     //it makes sense to treat that as simply no border at the wx level
@@ -4303,7 +4348,7 @@ void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
 
         if(wxstyle & wxBORDER_RAISED)
             gtkstyle = GTK_SHADOW_OUT;
-        else if (wxstyle & wxBORDER_SUNKEN)
+        else if ((wxstyle & wxBORDER_SUNKEN) || (wxstyle & wxBORDER_THEME))
             gtkstyle = GTK_SHADOW_IN;
 #if 0
         // Now obsolete