]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
always skip OnSize
[wxWidgets.git] / src / gtk / window.cpp
index e73b3ebb826074d2434e6eed4f68b06987f9ffdb..0c05229765a7edbdc1f6dccff3aaaca4c3938e83 100644 (file)
 
 #include "wx/gtk/private.h"
 #include "wx/gtk/private/win_gtk.h"
 
 #include "wx/gtk/private.h"
 #include "wx/gtk/private/win_gtk.h"
-#include <gdk/gdkkeysyms.h>
+
 #include <gdk/gdkx.h>
 
 #include <gdk/gdkx.h>
 
+#include <gdk/gdkkeysyms.h>
+#if GTK_CHECK_VERSION(3,0,0)
+#include <gdk/gdkkeysyms-compat.h>
+#endif
+
 #if !GTK_CHECK_VERSION(2,10,0)
     // GTK+ can reliably detect Meta key state only since 2.10 when
     // GDK_META_MASK was introduced -- there wasn't any way to detect it
 #if !GTK_CHECK_VERSION(2,10,0)
     // GTK+ can reliably detect Meta key state only since 2.10 when
     // GDK_META_MASK was introduced -- there wasn't any way to detect it
 
    Cursors, too, have been a constant source of pleasure. The main difficulty
    is that a GdkWindow inherits a cursor if the programmer sets a new cursor
 
    Cursors, too, have been a constant source of pleasure. The main difficulty
    is that a GdkWindow inherits a cursor if the programmer sets a new cursor
-   for the parent. To prevent this from doing too much harm, I use idle time
-   to set the cursor over and over again, starting from the toplevel windows
-   and ending with the youngest generation (speaking of parent and child windows).
+   for the parent. To prevent this from doing too much harm, SetCursor calls
+   GTKUpdateCursor, which will recursively re-set the cursors of all child windows.
    Also don't forget that cursors (like much else) are connected to GdkWindows,
    not GtkWidgets and that the "window" field of a GtkWidget might very well
    point to the GdkWindow of the parent widget (-> "window-less widget") and
    that the two obviously have very different meanings.
    Also don't forget that cursors (like much else) are connected to GdkWindows,
    not GtkWidgets and that the "window" field of a GtkWidget might very well
    point to the GdkWindow of the parent widget (-> "window-less widget") and
    that the two obviously have very different meanings.
-
 */
 
 //-----------------------------------------------------------------------------
 */
 
 //-----------------------------------------------------------------------------
@@ -281,11 +284,11 @@ wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget),
 
 extern "C" {
 static gboolean
 
 extern "C" {
 static gboolean
-gtk_window_expose_callback( GtkWidget* widget,
+gtk_window_expose_callback( GtkWidget*,
                             GdkEventExpose *gdk_event,
                             wxWindow *win )
 {
                             GdkEventExpose *gdk_event,
                             wxWindow *win )
 {
-    if (gdk_event->window == widget->window)
+    if (gdk_event->window == win->GTKGetDrawingWindow())
     {
         win->GetUpdateRegion() = wxRegion( gdk_event->region );
         win->GtkSendPaintEvents();
     {
         win->GetUpdateRegion() = wxRegion( gdk_event->region );
         win->GtkSendPaintEvents();
@@ -304,7 +307,10 @@ extern "C" {
 static gboolean
 expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win)
 {
 static gboolean
 expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win)
 {
-    if (gdk_event->window != widget->window)
+    if (gdk_event->window != gtk_widget_get_parent_window(win->m_wxwindow))
+        return false;
+
+    if (!win->IsShown())
         return false;
 
     const GtkAllocation& alloc = win->m_wxwindow->allocation;
         return false;
 
     const GtkAllocation& alloc = win->m_wxwindow->allocation;
@@ -679,15 +685,57 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
 
     event.SetTimestamp( gdk_event->time );
     event.SetId(win->GetId());
 
     event.SetTimestamp( gdk_event->time );
     event.SetId(win->GetId());
+
     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_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;
+
+    // Normally we take the state of modifiers directly from the low level GDK
+    // event but unfortunately GDK uses a different convention from MSW for the
+    // key events corresponding to the modifier keys themselves: in it, when
+    // e.g. Shift key is pressed, GDK_SHIFT_MASK is not set while it is set
+    // when Shift is released. Under MSW the situation is exactly reversed and
+    // the modifier corresponding to the key is set when it is pressed and
+    // unset when it is released. To ensure consistent behaviour between
+    // platforms (and because it seems to make slightly more sense, although
+    // arguably both behaviours are reasonable) we follow MSW here.
+    //
+    // Final notice: we set the flags to the desired value instead of just
+    // inverting them because they are not set correctly (i.e. in the same way
+    // as for the real events generated by the user) for wxUIActionSimulator-
+    // produced events and it seems better to keep that class code the same
+    // among all platforms and fix the discrepancy here instead of adding
+    // wxGTK-specific code to wxUIActionSimulator.
+    const bool isPress = gdk_event->type == GDK_KEY_PRESS;
+    switch ( gdk_event->keyval )
+    {
+        case GDK_Shift_L:
+        case GDK_Shift_R:
+            event.m_shiftDown = isPress;
+            break;
+
+        case GDK_Control_L:
+        case GDK_Control_R:
+            event.m_controlDown = isPress;
+            break;
+
+        case GDK_Alt_L:
+        case GDK_Alt_R:
+            event.m_altDown = isPress;
+            break;
+
+        case GDK_Meta_L:
+        case GDK_Meta_R:
+        case GDK_Super_L:
+        case GDK_Super_R:
+            event.m_metaDown = isPress;
+            break;
+    }
+
     event.m_rawCode = (wxUint32) gdk_event->keyval;
     event.m_rawCode = (wxUint32) gdk_event->keyval;
-    event.m_rawFlags = 0;
-#if wxUSE_UNICODE
-    event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval);
-#endif
+    event.m_rawFlags = gdk_event->hardware_keycode;
+
     wxGetMousePosition( &x, &y );
     win->ScreenToClient( &x, &y );
     event.m_x = x;
     wxGetMousePosition( &x, &y );
     win->ScreenToClient( &x, &y );
     event.m_x = x;
@@ -790,16 +838,21 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
     if ( !key_code )
         return false;
 
     if ( !key_code )
         return false;
 
-    // now fill all the other fields
-    wxFillOtherKeyEventFields(event, win, gdk_event);
-
     event.m_keyCode = key_code;
     event.m_keyCode = key_code;
+
 #if wxUSE_UNICODE
 #if wxUSE_UNICODE
-    if ( gdk_event->type == GDK_KEY_PRESS ||  gdk_event->type == GDK_KEY_RELEASE )
+    event.m_uniChar = gdk_keyval_to_unicode(key_code ? key_code : keysym);
+    if ( !event.m_uniChar && event.m_keyCode <= WXK_DELETE )
     {
     {
-        event.m_uniChar = key_code;
+        // Set Unicode key code to the ASCII equivalent for compatibility. E.g.
+        // let RETURN generate the key event with both key and Unicode key
+        // codes of 13.
+        event.m_uniChar = event.m_keyCode;
     }
     }
-#endif
+#endif // wxUSE_UNICODE
+
+    // now fill all the other fields
+    wxFillOtherKeyEventFields(event, win, gdk_event);
 
     return true;
 }
 
     return true;
 }
@@ -821,6 +874,41 @@ struct wxGtkIMData
     }
 };
 
     }
 };
 
+namespace
+{
+
+// Send wxEVT_CHAR_HOOK event to the parent of the window and if it wasn't
+// processed, send wxEVT_CHAR to the window itself. Return true if either of
+// them was handled.
+bool
+SendCharHookAndCharEvents(const wxKeyEvent& event, wxWindow *win)
+{
+    // wxEVT_CHAR_HOOK must be sent to the top level parent window to allow it
+    // to handle key events in all of its children unless the mouse is captured
+    // in which case we consider that the keyboard should be "captured" too.
+    if ( !g_captureWindow )
+    {
+        wxWindow * const parent = wxGetTopLevelParent(win);
+        if ( parent )
+        {
+            // We need to make a copy of the event object because it is
+            // modified while it's handled, notably its WasProcessed() flag
+            // is set after it had been processed once.
+            wxKeyEvent eventCharHook(event);
+            eventCharHook.SetEventType(wxEVT_CHAR_HOOK);
+            if ( parent->HandleWindowEvent(eventCharHook) )
+                return true;
+        }
+    }
+
+    // As above, make a copy of the event first.
+    wxKeyEvent eventChar(event);
+    eventChar.SetEventType(wxEVT_CHAR);
+    return win->HandleWindowEvent(eventChar);
+}
+
+} // anonymous namespace
+
 extern "C" {
 static gboolean
 gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
 extern "C" {
 static gboolean
 gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
@@ -848,8 +936,10 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
         return_after_IM = true;
     }
 
         return_after_IM = true;
     }
 
-    if ((!ret) && (win->m_imData != NULL))
+    if (!ret && win->m_imData)
     {
     {
+        win->m_imData->lastKeyEvent = gdk_event;
+
         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
         // docs, if IM filter returns true, no further processing should be done.
         // we should send the key_down event anyway.
         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
         // docs, if IM filter returns true, no further processing should be done.
         // we should send the key_down event anyway.
@@ -937,21 +1027,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
 #endif
             }
 
 #endif
             }
 
-            // Implement OnCharHook by checking ancestor top level windows
-            wxWindow *parent = win;
-            while (parent && !parent->IsTopLevel())
-                parent = parent->GetParent();
-            if (parent)
-            {
-                event.SetEventType( wxEVT_CHAR_HOOK );
-                ret = parent->HandleWindowEvent( event );
-            }
-
-            if (!ret)
-            {
-                event.SetEventType(wxEVT_CHAR);
-                ret = win->HandleWindowEvent( event );
-            }
+            ret = SendCharHookAndCharEvents(event, win);
         }
     }
 
         }
     }
 
@@ -983,13 +1059,6 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context),
     if( data.empty() )
         return;
 
     if( data.empty() )
         return;
 
-    bool ret = false;
-
-    // Implement OnCharHook by checking ancestor top level windows
-    wxWindow *parent = window;
-    while (parent && !parent->IsTopLevel())
-        parent = parent->GetParent();
-
     for( wxString::const_iterator pstr = data.begin(); pstr != data.end(); ++pstr )
     {
 #if wxUSE_UNICODE
     for( wxString::const_iterator pstr = data.begin(); pstr != data.end(); ++pstr )
     {
 #if wxUSE_UNICODE
@@ -1017,17 +1086,7 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context),
 #endif
         }
 
 #endif
         }
 
-        if (parent)
-        {
-            event.SetEventType( wxEVT_CHAR_HOOK );
-            ret = parent->HandleWindowEvent( event );
-        }
-
-        if (!ret)
-        {
-            event.SetEventType(wxEVT_CHAR);
-            ret = window->HandleWindowEvent( event );
-        }
+        SendCharHookAndCharEvents(event, window);
     }
 }
 }
     }
 }
 }
@@ -1831,7 +1890,7 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win)
     if (win->m_imData)
     {
         gtk_im_context_set_client_window( win->m_imData->context,
     if (win->m_imData)
     {
         gtk_im_context_set_client_window( win->m_imData->context,
-                                          widget->window);
+            win->m_wxwindow ? win->GTKGetDrawingWindow() : widget->window);
     }
 
     // We cannot set colours and fonts before the widget
     }
 
     // We cannot set colours and fonts before the widget
@@ -1847,6 +1906,8 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win)
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
     win->GTKProcessEvent( event );
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
     win->GTKProcessEvent( event );
+
+    win->GTKUpdateCursor(true, false);
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
@@ -1925,30 +1986,6 @@ void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget),
 
 } // extern "C"
 
 
 } // 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
 // ----------------------------------------------------------------------------
 // this wxWindowBase function is implemented here (in platform-specific file)
 // because it is static and so couldn't be made virtual
@@ -1973,8 +2010,7 @@ void wxWindowGTK::AddChildGTK(wxWindowGTK* child)
 
     gtk_widget_set_size_request(
         child->m_widget, child->m_width, child->m_height);
 
     gtk_widget_set_size_request(
         child->m_widget, child->m_width, child->m_height);
-    gtk_fixed_put(
-        GTK_FIXED(m_wxwindow), child->m_widget, child->m_x, child->m_y);
+    pizza->put(child->m_widget, child->m_x, child->m_y);
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
@@ -2021,9 +2057,7 @@ wxMouseState wxGetMouseState()
 // method
 #ifdef __WXUNIVERSAL__
     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK, wxWindowBase)
 // method
 #ifdef __WXUNIVERSAL__
     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK, wxWindowBase)
-#else // __WXGTK__
-    IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
-#endif // __WXUNIVERSAL__/__WXGTK__
+#endif // __WXUNIVERSAL__
 
 void wxWindowGTK::Init()
 {
 
 void wxWindowGTK::Init()
 {
@@ -2112,7 +2146,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
 #endif
 
 
 #endif
 
 
-    m_wxwindow = wxPizza::New(m_windowStyle,this);
+    m_wxwindow = wxPizza::New(m_windowStyle);
 #ifndef __WXUNIVERSAL__
     if (HasFlag(wxPizza::BORDER_STYLES))
     {
 #ifndef __WXUNIVERSAL__
     if (HasFlag(wxPizza::BORDER_STYLES))
     {
@@ -2235,6 +2269,12 @@ wxWindowGTK::~wxWindowGTK()
     // delete before the widgets to avoid a crash on solaris
     delete m_imData;
 
     // delete before the widgets to avoid a crash on solaris
     delete m_imData;
 
+    // avoid problem with GTK+ 2.18 where a frozen window causes the whole
+    // TLW to be frozen, and if the window is then destroyed, nothing ever
+    // gets painted again
+    if (IsFrozen())
+        DoThaw();
+
     if (m_widget)
     {
         // Note that gtk_widget_destroy() does not destroy the widget, it just
     if (m_widget)
     {
         // Note that gtk_widget_destroy() does not destroy the widget, it just
@@ -2382,6 +2422,11 @@ void wxWindowGTK::PostCreation()
         gtk_widget_show( m_widget );
 }
 
         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",
 void wxWindowGTK::ConnectWidget( GtkWidget *widget )
 {
     g_signal_connect (widget, "key_press_event",
@@ -2579,40 +2624,7 @@ void wxWindowGTK::OnInternalIdle()
         m_needsStyleChange = false;
     }
 
         m_needsStyleChange = false;
     }
 
-    wxCursor cursor = m_cursor;
-    if (g_globalCursor.Ok()) cursor = g_globalCursor;
-
-    if (cursor.Ok())
-    {
-        /* I now set the cursor anew in every OnInternalIdle call
-           as setting the cursor in a parent window also effects the
-           windows above so that checking for the current cursor is
-           not possible. */
-
-        if (m_wxwindow && (m_wxwindow != m_widget))
-        {
-            GdkWindow *window = m_wxwindow->window;
-            if (window)
-                gdk_window_set_cursor( window, cursor.GetCursor() );
-
-            if (!g_globalCursor.Ok())
-                cursor = *wxSTANDARD_CURSOR;
-
-            window = m_widget->window;
-            if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
-                gdk_window_set_cursor( window, cursor.GetCursor() );
-
-        }
-        else if ( m_widget )
-        {
-            GdkWindow *window = m_widget->window;
-            if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) )
-               gdk_window_set_cursor( window, cursor.GetCursor() );
-        }
-    }
-
-    if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+    wxWindowBase::OnInternalIdle();
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
@@ -2686,10 +2698,9 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
             }
         }
 
             }
         }
 
-        int border_x, border_y;
-        WX_PIZZA(m_wxwindow)->get_border_widths(border_x, border_y);
-        w -= 2 * border_x;
-        h -= 2 * border_y;
+        const wxSize sizeBorders = DoGetBorderSize();
+        w -= sizeBorders.x;
+        h -= sizeBorders.y;
 
         if (w < 0)
             w = 0;
 
         if (w < 0)
             w = 0;
@@ -2701,6 +2712,17 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
     if (height) *height = h;
 }
 
     if (height) *height = h;
 }
 
+wxSize wxWindowGTK::DoGetBorderSize() const
+{
+    if ( !m_wxwindow )
+        return wxWindowBase::DoGetBorderSize();
+
+    int x, y;
+    WX_PIZZA(m_wxwindow)->get_border_widths(x, y);
+
+    return 2*wxSize(x, y);
+}
+
 void wxWindowGTK::DoGetPosition( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 void wxWindowGTK::DoGetPosition( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
@@ -3443,33 +3465,40 @@ bool wxWindowGTK::SetCursor( const wxCursor &cursor )
     return true;
 }
 
     return true;
 }
 
-void wxWindowGTK::GTKUpdateCursor()
+void wxWindowGTK::GTKUpdateCursor(bool update_self /*=true*/, bool recurse /*=true*/)
 {
 {
-    wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
-    if ( cursor.Ok() )
+    if (update_self)
     {
     {
-        wxArrayGdkWindows windowsThis;
-        GdkWindow * const winThis = GTKGetWindow(windowsThis);
-        if ( winThis )
-        {
-            gdk_window_set_cursor(winThis, cursor.GetCursor());
-        }
-        else
+        wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
+        if ( cursor.Ok() )
         {
         {
-            const size_t count = windowsThis.size();
-            for ( size_t n = 0; n < count; n++ )
+            wxArrayGdkWindows windowsThis;
+            GdkWindow* window = GTKGetWindow(windowsThis);
+            if (window)
+                gdk_window_set_cursor( window, cursor.GetCursor() );
+            else
             {
             {
-                GdkWindow *win = windowsThis[n];
-                if ( !win )
+                const size_t count = windowsThis.size();
+                for ( size_t n = 0; n < count; n++ )
                 {
                 {
-                    wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?"));
-                    continue;
+                    GdkWindow *win = windowsThis[n];
+                    // It can be zero if the window has not been realized yet.
+                    if ( win )
+                    {
+                        gdk_window_set_cursor(win, cursor.GetCursor());
+                    }
                 }
                 }
-
-                gdk_window_set_cursor(win, cursor.GetCursor());
             }
         }
     }
             }
         }
     }
+
+    if (recurse)
+    {
+        for (wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it)
+        {
+            (*it)->GTKUpdateCursor( true );
+        }
+    }
 }
 
 void wxWindowGTK::WarpPointer( int x, int y )
 }
 
 void wxWindowGTK::WarpPointer( int x, int y )
@@ -3557,6 +3586,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
             if (!GTK_WIDGET_MAPPED (w))
                 return;
 
             if (!GTK_WIDGET_MAPPED (w))
                 return;
 
+        GdkWindow* window = GTKGetDrawingWindow();
         if (rect)
         {
             int x = rect->x;
         if (rect)
         {
             int x = rect->x;
@@ -3567,23 +3597,26 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
             r.y = rect->y;
             r.width = rect->width;
             r.height = rect->height;
             r.y = rect->y;
             r.width = rect->width;
             r.height = rect->height;
-            gdk_window_invalidate_rect( m_wxwindow->window, &r, TRUE );
+            gdk_window_invalidate_rect(window, &r, true);
         }
         else
         }
         else
-            gdk_window_invalidate_rect( m_wxwindow->window, NULL, TRUE );
+            gdk_window_invalidate_rect(window, NULL, true);
     }
 }
 
 void wxWindowGTK::Update()
 {
     }
 }
 
 void wxWindowGTK::Update()
 {
-    if (m_widget && m_widget->window)
+    if (m_widget && GTK_WIDGET_MAPPED(m_widget))
     {
         GdkDisplay* display = gtk_widget_get_display(m_widget);
         // Flush everything out to the server, and wait for it to finish.
         // This ensures nothing will overwrite the drawing we are about to do.
         gdk_display_sync(display);
 
     {
         GdkDisplay* display = gtk_widget_get_display(m_widget);
         // Flush everything out to the server, and wait for it to finish.
         // This ensures nothing will overwrite the drawing we are about to do.
         gdk_display_sync(display);
 
-        gdk_window_process_updates(m_widget->window, TRUE);
+        GdkWindow* window = GTKGetDrawingWindow();
+        if (window == NULL)
+            window = m_widget->window;
+        gdk_window_process_updates(window, true);
 
         // Flush again, but no need to wait for it to finish
         gdk_display_flush(display);
 
         // Flush again, but no need to wait for it to finish
         gdk_display_flush(display);
@@ -3688,7 +3721,7 @@ void wxWindowGTK::GtkSendPaintEvents()
                         rect.height = upd.GetHeight();
 
                         gtk_paint_flat_box( parent->m_widget->style,
                         rect.height = upd.GetHeight();
 
                         gtk_paint_flat_box( parent->m_widget->style,
-                                    m_wxwindow->window,
+                                    GTKGetDrawingWindow(),
                                     (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
                                     GTK_SHADOW_NONE,
                                     &rect,
                                     (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
                                     GTK_SHADOW_NONE,
                                     &rect,
@@ -3755,19 +3788,23 @@ void wxWindowGTK::DoSetToolTip( wxToolTip *tip )
     {
         GtkWidget *w = GetConnectWidget();
         wxToolTip::GTKApply(w, NULL);
     {
         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 )
 {
     }
 }
 
 void wxWindowGTK::GTKApplyToolTip( GtkTooltips *tips, const gchar *tip )
 {
-    gtk_tooltips_set_tip(tips, GetConnectWidget(), tip, NULL);
+    GtkWidget *w = GetConnectWidget();
+
+#if GTK_CHECK_VERSION(2, 12, 0)
+    if (!gtk_check_version(2, 12, 0))
+    {
+        gtk_widget_set_tooltip_text (w, tip);
+    }
+    else
+#endif
+    {
+        gtk_tooltips_set_tip(tips, w, tip, NULL);
+    }
 }
 #endif // wxUSE_TOOLTIPS
 
 }
 #endif // wxUSE_TOOLTIPS
 
@@ -3902,12 +3939,30 @@ void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle)
 
 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style)
 {
 
 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);
         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
     else
+    {
         gtk_widget_modify_style(m_widget, style);
         gtk_widget_modify_style(m_widget, style);
+    }
 }
 
 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 }
 
 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
@@ -3919,7 +3974,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
         GdkWindow *window;
         if ( m_wxwindow )
         {
         GdkWindow *window;
         if ( m_wxwindow )
         {
-            window = m_wxwindow->window;
+            window = GTKGetDrawingWindow();
         }
         else
         {
         }
         else
         {
@@ -3962,23 +4017,6 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 
 #if wxUSE_MENUS_NATIVE
 
 
 #if wxUSE_MENUS_NATIVE
 
-static void SetInvokingWindow( wxMenu *menu, wxWindow* win )
-{
-    menu->SetInvokingWindow( win );
-
-    wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
-    while (node)
-    {
-        wxMenuItem *menuitem = node->GetData();
-        if (menuitem->IsSubMenu())
-        {
-            SetInvokingWindow( menuitem->GetSubMenu(), win );
-        }
-
-        node = node->GetNext();
-    }
-}
-
 extern "C" {
 static
 void wxPopupMenuPositionCallback( GtkMenu *menu,
 extern "C" {
 static
 void wxPopupMenuPositionCallback( GtkMenu *menu,
@@ -4005,10 +4043,6 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 {
     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
 
 {
     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
 
-    wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") );
-
-    SetInvokingWindow( menu, this );
-
     menu->UpdateUI();
 
     wxPoint pos;
     menu->UpdateUI();
 
     wxPoint pos;
@@ -4085,7 +4119,7 @@ bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const
 
 GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
 
 GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return m_wxwindow ? m_wxwindow->window : m_widget->window;
+    return m_wxwindow ? GTKGetDrawingWindow() : m_widget->window;
 }
 
 bool wxWindowGTK::SetFont( const wxFont &font )
 }
 
 bool wxWindowGTK::SetFont( const wxFont &font )
@@ -4108,7 +4142,7 @@ void wxWindowGTK::DoCaptureMouse()
 
     GdkWindow *window = NULL;
     if (m_wxwindow)
 
     GdkWindow *window = NULL;
     if (m_wxwindow)
-        window = m_wxwindow->window;
+        window = GTKGetDrawingWindow();
     else
         window = GetConnectWidget()->window;
 
     else
         window = GetConnectWidget()->window;
 
@@ -4141,7 +4175,7 @@ void wxWindowGTK::DoReleaseMouse()
 
     GdkWindow *window = NULL;
     if (m_wxwindow)
 
     GdkWindow *window = NULL;
     if (m_wxwindow)
-        window = m_wxwindow->window;
+        window = GTKGetDrawingWindow();
     else
         window = GetConnectWidget()->window;
 
     else
         window = GetConnectWidget()->window;
 
@@ -4426,7 +4460,7 @@ extern "C"
 
 // this is called if we attempted to freeze unrealized widget when it finally
 // is realized (and so can be frozen):
 
 // this is called if we attempted to freeze unrealized widget when it finally
 // is realized (and so can be frozen):
-static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data))
+static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win)
 {
     wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) );
     wxASSERT( GTK_WIDGET_REALIZED(w) );
 {
     wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) );
     wxASSERT( GTK_WIDGET_REALIZED(w) );
@@ -4435,10 +4469,13 @@ static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data))
     (
         w,
         (void*)wx_frozen_widget_realize,
     (
         w,
         (void*)wx_frozen_widget_realize,
-        NULL
+        win
     );
 
     );
 
-    gdk_window_freeze_updates(w->window);
+    GdkWindow* window = w->window;
+    if (w == win->m_wxwindow)
+        window = win->GTKGetDrawingWindow();
+    gdk_window_freeze_updates(window);
 }
 
 } // extern "C"
 }
 
 } // extern "C"
@@ -4457,12 +4494,15 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget *w)
             w,
             "realize",
             G_CALLBACK(wx_frozen_widget_realize),
             w,
             "realize",
             G_CALLBACK(wx_frozen_widget_realize),
-            NULL
+            this
         );
         return;
     }
 
         );
         return;
     }
 
-    gdk_window_freeze_updates(w->window);
+    GdkWindow* window = w->window;
+    if (w == m_wxwindow)
+        window = GTKGetDrawingWindow();
+    gdk_window_freeze_updates(window);
 }
 
 void wxWindowGTK::GTKThawWidget(GtkWidget *w)
 }
 
 void wxWindowGTK::GTKThawWidget(GtkWidget *w)
@@ -4477,12 +4517,15 @@ void wxWindowGTK::GTKThawWidget(GtkWidget *w)
         (
             w,
             (void*)wx_frozen_widget_realize,
         (
             w,
             (void*)wx_frozen_widget_realize,
-            NULL
+            this
         );
         return;
     }
 
         );
         return;
     }
 
-    gdk_window_thaw_updates(w->window);
+    GdkWindow* window = w->window;
+    if (w == m_wxwindow)
+        window = GTKGetDrawingWindow();
+    gdk_window_thaw_updates(window);
 }
 
 void wxWindowGTK::DoFreeze()
 }
 
 void wxWindowGTK::DoFreeze()