wxGTK:
 
 - Automatically use stock items for the menu items with standard ids
+- Setting cursor now works for all controls
 
 
 2.7.0
 
     // implementation
     // --------------
 
-    bool IsOwnGtkWindow( GdkWindow *window );
-
     // Since this wxButton doesn't derive from wxButtonBase (why?) we need
     // to override this here too...
     virtual bool ShouldInheritColours() const { return false; }
 
 protected:
     virtual wxSize DoGetBestSize() const;
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxButton)
 
     // implementation
     // --------------
 
-    bool IsOwnGtkWindow( GdkWindow *window );
-    void OnInternalIdle();
-
     GtkWidget *m_widgetCheckbox;
     GtkWidget *m_widgetLabel;
 
 
 protected:
     virtual wxSize DoGetBestSize() const;
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
     void DoSet3StateValue(wxCheckBoxState state);
     wxCheckBoxState DoGet3StateValue() const;
 
     static wxVisualAttributes
     GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
 
-    virtual bool IsOwnGtkWindow( GdkWindow *window );
-
 protected:
     wxList m_clientList;    // contains the client data for the items
 
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual wxSize DoGetBestSize() const;
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
+
     virtual int DoAppend(const wxString& item);
     virtual int DoInsert(const wxString& item, unsigned int pos);
 
     virtual void DoSetItemClientObject(unsigned int n, wxClientData* clientData);
     virtual wxClientData* DoGetItemClientObject(unsigned int n) const;
 
-    virtual wxSize DoGetBestSize() const;
-
 private:
     // common part of Create() and DoAppend()
     int GtkAddHelper(GtkWidget *menu, unsigned int pos, const wxString& item);
 
     void DisableEvents();
     void EnableEvents();
     GtkWidget* GetConnectWidget();
-    bool IsOwnGtkWindow( GdkWindow *window );
 
     wxCONTROL_ITEMCONTAINER_CLIENTDATAOBJECT_RECAST
 
 
 protected:
     // From wxWindowGTK:
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
     // From wxItemContainer:
     virtual int DoAppend(const wxString& item);
 
 
     virtual wxVisualAttributes GetDefaultAttributes() const;
 
+    virtual void OnInternalIdle();
+
 protected:
     virtual wxSize DoGetBestSize() const;
     void PostCreation(const wxSize& size);
 
     // implementation from now on
 
     GtkWidget *GetConnectWidget();
-    bool IsOwnGtkWindow( GdkWindow *window );
-    void OnInternalIdle();
 
 #if wxUSE_TOOLTIPS
     void ApplyToolTip( GtkTooltips *tips, const wxChar *tip );
 
 protected:
     virtual wxSize DoGetBestSize() const;
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
+
     virtual void DoSetSelection(int n, bool select);
     virtual int DoAppend(const wxString& item);
     virtual void DoInsertItems(const wxArrayString& items, unsigned int pos);
     virtual wxClientData* DoGetItemClientObject(unsigned int n) const;
     virtual int DoListHitTest(const wxPoint& point) const;
 
-    void DoApplyWidgetStyle(GtkRcStyle *style);
-
 private:
     void Init(); //common construction
 
 
     void SetConstraintSizes(bool recurse);
     bool DoPhase(int phase);
 #endif
-    // report if window belongs to notebook
-    bool IsOwnGtkWindow( GdkWindow *window );
 
     // common part of all ctors
     void Init();
 
 protected:
     // set all page's attributes
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
     // remove one page from the notebook but do not destroy it
     virtual wxNotebookPage *DoRemovePage(size_t nPage);
 
     void SetFocus();
     void GtkDisableEvents();
     void GtkEnableEvents();
-    bool IsOwnGtkWindow( GdkWindow *window );
 #if wxUSE_TOOLTIPS
     void ApplyToolTip( GtkTooltips *tips, const wxChar *tip );
 #endif // wxUSE_TOOLTIPS
     virtual void DoSetItemToolTip(unsigned int n, wxToolTip *tooltip);
 #endif
 
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
     virtual bool GTKWidgetNeedsMnemonic() const;
     virtual void GTKWidgetDoSetMnemonic(GtkWidget* w);
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifndef __GTKRADIOBUTTONH__
-#define __GTKRADIOBUTTONH__
+#ifndef _WX_GTK_RADIOBUT_H_
+#define _WX_GTK_RADIOBUT_H_
 
 //-----------------------------------------------------------------------------
 // wxRadioButton
 
     virtual bool IsRadioButton() const { return TRUE; }
 
-    bool IsOwnGtkWindow( GdkWindow *window );
-    void OnInternalIdle();
-
     bool m_blockEvent;
 
 protected:
-    void DoApplyWidgetStyle(GtkRcStyle *style);
     virtual wxSize DoGetBestSize() const;
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxRadioButton)
 };
 
-#endif // __GTKRADIOBUTTONH__
+#endif // _WX_GTK_RADIOBUT_H_
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifndef __GTKSCROLLBARH__
-#define __GTKSCROLLBARH__
+#ifndef _WX_GTK_SCROLLBAR_H_
+#define _WX_GTK_SCROLLBAR_H_
 
 #include "wx/defs.h"
 
     static wxVisualAttributes
     GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
     
-    // implementation
-    // --------------
-
-    bool IsOwnGtkWindow( GdkWindow *window );
+protected:
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxScrollBar)
 };
 
-#endif
-    // __GTKSCROLLBARH__
+#endif // _WX_GTK_SCROLLBAR_H_
 
     GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
     
     // implementation
-    bool IsOwnGtkWindow( GdkWindow *window );
-
     double m_pos;
     int m_scrollEventType;
     bool m_needThumbRelease;
 
+protected:
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
+
 private:
     DECLARE_DYNAMIC_CLASS(wxSlider)
 };
 
     // implementation
     void OnSize( wxSizeEvent &event );
 
-    bool IsOwnGtkWindow( GdkWindow *window );
-
     int m_pos;
 
 protected:
     virtual wxSize DoGetBestSize() const;
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
 private:
     DECLARE_EVENT_TABLE()
 
     // implementation
     void OnChar( wxKeyEvent &event );
     
-    bool IsOwnGtkWindow( GdkWindow *window );
     void GtkDisableEvents();
     void GtkEnableEvents();
 
 
 protected:
     virtual wxSize DoGetBestSize() const;
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
     // Widgets that use the style->base colour for the BG colour should
     // override this and return true.
 
     bool SetBackgroundColour(const wxColour& colour);
 
     GtkWidget* GetConnectWidget();
-    bool IsOwnGtkWindow( GdkWindow *window );
     void CalculateScrollbar();
-    void OnInternalIdle();
 
     void SetUpdateFont(bool WXUNUSED(update)) { }
 
 
 protected:
     virtual wxSize DoGetBestSize() const;
-    void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
     // common part of all ctors
     void Init();
 
     wxBitmap  m_bitmap;
 
     void OnSetBitmap();
-    bool IsOwnGtkWindow(GdkWindow *window);
-
-    virtual void OnInternalIdle();
 
 protected:
-    void DoApplyWidgetStyle(GtkRcStyle *style);
     virtual wxSize DoGetBestSize() const;
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxToggleBitmapButton)
     // implementation
     bool m_blockEvent;
 
-    bool IsOwnGtkWindow(GdkWindow *window);
-
-    virtual void OnInternalIdle();
-
 protected:
-    void DoApplyWidgetStyle(GtkRcStyle *style);
     virtual wxSize DoGetBestSize() const;
+    virtual void DoApplyWidgetStyle(GtkRcStyle *style);
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxToggleButton)
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifndef __GTKWINDOWH__
-#define __GTKWINDOWH__
+#ifndef _WX_GTK_WINDOW_H_
+#define _WX_GTK_WINDOW_H_
+
+#include "wx/dynarray.h"
 
 // helper structure that holds class that holds GtkIMContext object and
 // some additional data needed for key events processing
 struct wxGtkIMData;
 
+WX_DEFINE_EXPORTED_ARRAY_PTR(GdkWindow *, wxArrayGdkWindows);
+
 //-----------------------------------------------------------------------------
 // callback definition for inserting a window (internal)
 //-----------------------------------------------------------------------------
 
     virtual WXWidget GetHandle() const { return m_widget; }
 
+    // many important things are done here, this function must be called
+    // regularly
     virtual void OnInternalIdle();
 
     // Internal represention of Update()
     // widget where (most of) the input goes. even tooltips have
     // to be applied to all subwidgets.
     virtual GtkWidget* GetConnectWidget();
-    virtual bool IsOwnGtkWindow( GdkWindow *window );
     void ConnectWidget( GtkWidget *widget );
 
+    // Called from several event handlers
+    bool GTKCallbackCommonPrologue(struct _GdkEventAny *event) const;
+
 protected:
     // Override GTKWidgetNeedsMnemonic and return true if your
     // needs to set its mnemonic widget, such as for a 
     virtual bool GTKWidgetNeedsMnemonic() const;
     virtual void GTKWidgetDoSetMnemonic(GtkWidget* w);
 
+    // Get the GdkWindows making part of this window: usually there will be
+    // only one of them in which case it should be returned directly by this
+    // function. If there is more than one GdkWindow (can be the case for
+    // composite widgets), return NULL and fill in the provided array
+    //
+    // This is not pure virtual for backwards compatibility but almost
+    // certainly must be overridden in any wxControl-derived class!
+    virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
+
+    // Check if the given window makes part of this widget
+    bool GTKIsOwnWindow(GdkWindow *window) const;
+
+    // Set the focus to this window if its setting was delayed because the
+    // widget hadn't been realized when SetFocus() was called
+    //
+    // Return true if focus was set to us, false if nothing was done
+    bool GTKSetDelayedFocusIfNeeded();
+
 public:
     // Returns the default context which usually is anti-aliased
     PangoContext   *GtkGetPangoDefaultContext();
     // sets the border of a given GtkScrolledWindow from a wx style
     static void GtkScrolledWindowSetBorder(GtkWidget* w, int style);
 
+    // set the current cursor for all GdkWindows making part of this widget
+    // (see GTKGetWindow)
+    //
+    // should be called from OnInternalIdle() if it's overridden
+    void GTKUpdateCursor();
+
 private:
     enum ScrollUnit { ScrollUnit_Line, ScrollUnit_Page, ScrollUnit_Max };
 
 
 extern WXDLLIMPEXP_CORE wxWindow *wxFindFocusedChild(wxWindowGTK *win);
 
-#endif // __GTKWINDOWH__
+#endif // _WX_GTK_WINDOW_H_
 
     return true;
 }
 
-bool wxButton::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
     return GTK_BUTTON(m_widget)->event_window;
 }
 
 //-----------------------------------------------------------------------------
 
 extern bool           g_blockEventsOnDrag;
-extern wxCursor       g_globalCursor;
-extern wxWindowGTK   *g_delayedFocus;
 
 //-----------------------------------------------------------------------------
 // "clicked"
     gtk_widget_modify_style(m_widgetLabel, style);
 }
 
-bool wxCheckBox::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxCheckBox::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return window == GTK_BUTTON(m_widget)->event_window;
-}
-
-void wxCheckBox::OnInternalIdle()
-{
-    // Check if we have to show window now
-    if (GtkShowFromOnIdle()) return;
-    
-    wxCursor cursor = m_cursor;
-    if (g_globalCursor.Ok()) cursor = g_globalCursor;
-
-    GdkWindow *event_window = GTK_BUTTON(m_widgetCheckbox)->event_window;
-    if ( event_window && cursor.Ok() )
-    {
-        /* I now set the cursor the 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. */
-
-       gdk_window_set_cursor( event_window, cursor.GetCursor() );
-    }
-
-    if (g_delayedFocus == this)
-    {
-        if (GTK_WIDGET_REALIZED(m_widget))
-        {
-            gtk_widget_grab_focus( m_widget );
-            g_delayedFocus = NULL;
-        }
-    }
-
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+    return GTK_BUTTON(m_widgetCheckbox)->event_window;
 }
 
 wxSize wxCheckBox::DoGetBestSize() const
 
     return ret;
 }
 
-bool wxChoice::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxChoice::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
     return GTK_BUTTON(m_widget)->event_window;
 }
 
     return GTK_WIDGET( entry );
 }
 
-bool wxComboBox::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxComboBox::GTKGetWindow(wxArrayGdkWindows& windows) const
 {
-    GtkEntry *entry = NULL;
 #ifdef __WXGTK24__
     if (!gtk_check_version(2,4,0))
     {
-        entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
-        return (window == entry->text_area);
+        wxUnusedVar(windows);
+
+        return GTK_ENTRY(GTK_BIN(m_widget)->child)->text_area;
     }
     else
-#endif
+#endif // GTK+ 2.4
     {
-        entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
-        return ( (window == entry->text_area) ||
-                 (window == GTK_COMBO(m_widget)->button->window ) );
+        windows.push_back(GTK_ENTRY(GTK_COMBO(m_widget)->entry)->text_area);
+        windows.push_back(GTK_COMBO(m_widget)->button->window);
+
+        // indicate that we return multiple windows in the windows array
+        return NULL;
     }
 }
 
 
     return attr;
 }
 
+// ----------------------------------------------------------------------------
+// idle handling
+// ----------------------------------------------------------------------------
+
+void wxControl::OnInternalIdle()
+{
+    if ( GtkShowFromOnIdle() )
+        return;
+    
+    GTKUpdateCursor();
+
+    if ( wxUpdateUIEvent::CanUpdate(this) )
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+}
+
 #endif // wxUSE_CONTROLS
 
         gtk_widget_modify_style(GTK_WIDGET(GetNotebookPage(i)->m_label), style);
 }
 
-bool wxNotebook::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxNotebook::GTKGetWindow(wxArrayGdkWindows& windows) const
 {
-    return ((m_widget->window == window) ||
-            GTK_NOTEBOOK(m_widget)->event_window == window);
+    windows.push_back(m_widget->window);
+    windows.push_back(GTK_NOTEBOOK(m_widget)->event_window);
+
+    return NULL;
 }
 
 // static
 
 WX_DEFINE_LIST( wxRadioBoxButtonsInfoList );
 
 extern bool          g_blockEventsOnDrag;
-extern wxWindowGTK  *g_delayedFocus;
 
 //-----------------------------------------------------------------------------
 // "clicked"
 
 #endif // wxUSE_TOOLTIPS
 
-bool wxRadioBox::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxRadioBox::GTKGetWindow(wxArrayGdkWindows& windows) const
 {
-    if (window == m_widget->window)
-        return true;
+    windows.push_back(m_widget->window);
 
     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
     while (node)
     {
         GtkWidget *button = GTK_WIDGET( node->GetData()->button );
 
-        if (window == button->window)
-            return true;
+        windows.push_back(button->window);
 
         node = node->GetNext();
     }
 
-    return false;
+    return NULL;
 }
 
 void wxRadioBox::OnInternalIdle()
 {
-    // Check if we have to show window now
-    if (GtkShowFromOnIdle()) return;
-    
+    wxControl::OnInternalIdle();
+
     if ( m_lostFocus )
     {
         m_hasFocus = false;
 
         (void)GetEventHandler()->ProcessEvent( event );
     }
-
-    if (g_delayedFocus == this)
-    {
-        if (GTK_WIDGET_REALIZED(m_widget))
-        {
-            g_delayedFocus = NULL;
-            SetFocus();
-        }
-    }
-
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 // static
 
 //-----------------------------------------------------------------------------
 
 extern bool           g_blockEventsOnDrag;
-extern wxCursor       g_globalCursor;
-extern wxWindowGTK   *g_delayedFocus;
 
 //-----------------------------------------------------------------------------
 // "clicked"
     gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
 }
 
-bool wxRadioButton::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *
+wxRadioButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return window == GTK_BUTTON(m_widget)->event_window;
-}
-
-void wxRadioButton::OnInternalIdle()
-{
-    wxCursor cursor = m_cursor;
-    if (g_globalCursor.Ok()) cursor = g_globalCursor;
-
-    GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
-    if ( win && cursor.Ok())
-    {
-        /* I now set the cursor the 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. */
-
-       gdk_window_set_cursor( win, cursor.GetCursor() );
-    }
-
-    if (g_delayedFocus == this)
-    {
-        if (GTK_WIDGET_REALIZED(m_widget))
-        {
-            gtk_widget_grab_focus( m_widget );
-            g_delayedFocus = NULL;
-        }
-    }
-
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+    return GTK_BUTTON(m_widget)->event_window;
 }
 
 wxSize wxRadioButton::DoGetBestSize() const
 
     SetScrollbar(GetThumbPosition(), GetThumbSize(), range, GetPageSize());
 }
 
-bool wxScrollBar::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxScrollBar::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    GtkRange *range = GTK_RANGE(m_widget);
-    return ( (window == GTK_WIDGET(range)->window) );
+    return GTK_WIDGET(GTK_RANGE(m_widget))->window;
 }
 
 // static
 
     return int(gtk_range_get_adjustment (GTK_RANGE (m_widget))->step_increment);
 }
 
-bool wxSlider::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxSlider::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    GtkRange *range = GTK_RANGE(m_widget);
-    return (range->event_window == window);
+    return GTK_RANGE(m_widget)->event_window;
 }
 
 // static
 
     gtk_widget_set_size_request( m_widget, m_width, m_height );
 }
 
-bool wxSpinButton::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxSpinButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return GTK_SPIN_BUTTON(m_widget)->panel == window;
+    return GTK_SPIN_BUTTON(m_widget)->panel;
 }
 
 wxSize wxSpinButton::DoGetBestSize() const
 
     event.Skip();
 }
 
-bool wxSpinCtrl::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxSpinCtrl::GTKGetWindow(wxArrayGdkWindows& windows) const
 {
     GtkSpinButton* spinbutton = GTK_SPIN_BUTTON(m_widget);
-    return window == spinbutton->entry.text_area || window == spinbutton->panel;
+
+    windows.push_back(spinbutton->entry.text_area);
+    windows.push_back(spinbutton->panel);
+
+    return NULL;
 }
 
 wxSize wxSpinCtrl::DoGetBestSize() const
 {
     wxSize ret( wxControl::DoGetBestSize() );
-    wxSize best(95, ret.y);
+    wxSize best(95, ret.y); // FIXME: 95?
     CacheBestSize(best);
     return best;
 }
 
 #include "wx/gtk/private.h"
 #include <gdk/gdkkeysyms.h>
 
-//-----------------------------------------------------------------------------
-// data
-//-----------------------------------------------------------------------------
-
-extern wxWindowGTK *g_delayedFocus;
-
 // ----------------------------------------------------------------------------
 // helpers
 // ----------------------------------------------------------------------------
     return GTK_WIDGET(m_text);
 }
 
-bool wxTextCtrl::IsOwnGtkWindow( GdkWindow *window )
+GdkWindow *wxTextCtrl::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
     if ( IsMultiLine() )
     {
-        return window == gtk_text_view_get_window( GTK_TEXT_VIEW( m_text ), GTK_TEXT_WINDOW_TEXT );  // pure guesswork
+        return gtk_text_view_get_window(GTK_TEXT_VIEW(m_text),
+                                        GTK_TEXT_WINDOW_TEXT );
     }
     else
     {
-        return (window == GTK_ENTRY(m_text)->text_area);
+        return GTK_ENTRY(m_text)->text_area;
     }
 }
 
     event.Enable( CanRedo() );
 }
 
-void wxTextCtrl::OnInternalIdle()
-{
-    // Check if we have to show window now
-    if (GtkShowFromOnIdle()) return;
-
-    if (g_delayedFocus == this)
-    {
-        if (GTK_WIDGET_REALIZED(m_widget))
-        {
-            gtk_widget_grab_focus( m_widget );
-            g_delayedFocus = NULL;
-        }
-    }
-    
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
-}
-
 wxSize wxTextCtrl::DoGetBestSize() const
 {
     // FIXME should be different for multi-line controls...
 
 #include "wx/gtk/private.h"
 
 extern bool      g_blockEventsOnDrag;
-extern wxCursor   g_globalCursor;
 
 extern "C" {
 static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb)
     gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
 }
 
-bool wxToggleBitmapButton::IsOwnGtkWindow(GdkWindow *window)
+GdkWindow *
+wxToggleBitmapButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return window == GTK_BUTTON(m_widget)->event_window;
+    return GTK_BUTTON(m_widget)->event_window;
 }
 
-void wxToggleBitmapButton::OnInternalIdle()
-{
-    // Check if we have to show window now
-    if (GtkShowFromOnIdle()) return;
-    
-    wxCursor cursor = m_cursor;
-
-    if (g_globalCursor.Ok())
-        cursor = g_globalCursor;
-
-    GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
-    if ( win && cursor.Ok() )
-    {
-      /* I now set the cursor the 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. */
-
-        gdk_window_set_cursor(win, cursor.GetCursor());
-    }
-
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
-}
-
-
 // Get the "best" size for this control.
 wxSize wxToggleBitmapButton::DoGetBestSize() const
 {
     gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
 }
 
-bool wxToggleButton::IsOwnGtkWindow(GdkWindow *window)
+GdkWindow *
+wxToggleButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return window == GTK_BUTTON(m_widget)->event_window;
+    return GTK_BUTTON(m_widget)->event_window;
 }
 
-void wxToggleButton::OnInternalIdle()
-{
-    wxCursor cursor = m_cursor;
-
-    if (g_globalCursor.Ok())
-        cursor = g_globalCursor;
-
-    GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
-    if ( win && cursor.Ok() )
-    {
-      /* I now set the cursor the 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. */
-
-        gdk_window_set_cursor(win, cursor.GetCursor());
-    }
-
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
-}
-
-
 // Get the "best" size for this control.
 wxSize wxToggleButton::DoGetBestSize() const
 {
 
     return win;
 }
 
+// ----------------------------------------------------------------------------
+// common event handlers helpers
+// ----------------------------------------------------------------------------
+
+bool wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
+{
+    DEBUG_MAIN_THREAD
+
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (!m_hasVMT)
+        return false;
+    if (g_blockEventsOnDrag)
+        return true;
+    if (g_blockEventsOnScroll)
+        return true;
+
+    if (!GTKIsOwnWindow(event->window))
+        return false;
+
+    return true;
+}
+
+// overloads for all GDK event types we use here: we need to have this as
+// GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact,
+// derives from it in the sense that the structs have the same layout
+#define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T)                                  \
+    static bool wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win)       \
+    {                                                                         \
+        return win->GTKCallbackCommonPrologue((GdkEventAny *)event);          \
+    }
+
+wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton)
+wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion)
+wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing)
+
+#undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD
+
+// send the wxChildFocusEvent and wxFocusEvent, common code of
+// gtk_window_focus_in_callback() and SetFocus()
+static bool DoSendFocusEvents(wxWindow *win)
+{
+    // Notify the parent keeping track of focus for the kbd navigation
+    // purposes that we got it.
+    wxChildFocusEvent eventChildFocus(win);
+    (void)win->GetEventHandler()->ProcessEvent(eventChildFocus);
+
+    wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId());
+    eventFocus.SetEventObject(win);
+
+    return win->GetEventHandler()->ProcessEvent(eventFocus);
+}
+
+// all event handlers must have C linkage as they're called from GTK+ C code
+extern "C"
+{
+
 //-----------------------------------------------------------------------------
 // "button_press_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_button_press_callback( GtkWidget *widget,
                                   GdkEventButton *gdk_event,
                                   wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-/*
-    wxPrintf( wxT("1) OnButtonPress from ") );
-    if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-        wxPrintf( win->GetClassInfo()->GetClassName() );
-    wxPrintf( wxT(".\n") );
-*/
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return TRUE;
-    if (g_blockEventsOnScroll) return TRUE;
-
-    if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+    if ( !wxGtkCallbackCommonPrologue(gdk_event, win) )
+        return FALSE;
 
     if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus())
     {
         gtk_widget_grab_focus( win->m_wxwindow );
-/*
-        wxPrintf( wxT("GrabFocus from ") );
-        if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-            wxPrintf( win->GetClassInfo()->GetClassName() );
-        wxPrintf( wxT(".\n") );
-*/
     }
 
     // GDK sends surplus button down events
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "button_release_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_button_release_callback( GtkWidget *widget,
                                     GdkEventButton *gdk_event,
                                     wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return FALSE;
-    if (g_blockEventsOnScroll) return FALSE;
-
-    if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+    if ( !wxGtkCallbackCommonPrologue(gdk_event, win) )
+        return FALSE;
 
     wxEventType event_type = wxEVT_NULL;
 
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "motion_notify_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_motion_notify_callback( GtkWidget *widget,
                                    GdkEventMotion *gdk_event,
                                    wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return FALSE;
-    if (g_blockEventsOnScroll) return FALSE;
-
-    if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+    if ( !wxGtkCallbackCommonPrologue(gdk_event, win) )
+        return FALSE;
 
     if (gdk_event->is_hint)
     {
         gdk_event->y = y;
     }
 
-/*
-    printf( "OnMotion from " );
-    if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-      printf( win->GetClassInfo()->GetClassName() );
-    printf( ".\n" );
-*/
-
     wxMouseEvent event( wxEVT_MOTION );
     InitMouseEvent(win, event, gdk_event);
 
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "scroll_event", (mouse wheel event)
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
 {
 
     return win->GetEventHandler()->ProcessEvent(event);
 }
-}
 
 //-----------------------------------------------------------------------------
 // "popup-menu"
 //-----------------------------------------------------------------------------
-extern "C" {
+
 static gboolean wxgtk_window_popup_menu_callback(GtkWidget*, wxWindowGTK* win)
 {
-    wxContextMenuEvent event(
-        wxEVT_CONTEXT_MENU,
-        win->GetId(),
-        wxPoint(-1, -1));
+    wxContextMenuEvent event(wxEVT_CONTEXT_MENU, win->GetId(), wxPoint(-1, -1));
     event.SetEventObject(win);
     return win->GetEventHandler()->ProcessEvent(event);
 }
-}
 
 //-----------------------------------------------------------------------------
 // "focus_in_event"
 //-----------------------------------------------------------------------------
 
-// send the wxChildFocusEvent and wxFocusEvent, common code of
-// gtk_window_focus_in_callback() and SetFocus()
-static bool DoSendFocusEvents(wxWindow *win)
-{
-    // Notify the parent keeping track of focus for the kbd navigation
-    // purposes that we got it.
-    wxChildFocusEvent eventChildFocus(win);
-    (void)win->GetEventHandler()->ProcessEvent(eventChildFocus);
-
-    wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId());
-    eventFocus.SetEventObject(win);
-
-    return win->GetEventHandler()->ProcessEvent(eventFocus);
-}
-
-extern "C" {
 static gboolean
 gtk_window_focus_in_callback( GtkWidget *widget,
                               GdkEventFocus *WXUNUSED(event),
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "focus_out_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_focus_out_callback( GtkWidget *widget,
                                GdkEventFocus *gdk_event,
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "enter_notify_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_enter_callback( GtkWidget *widget,
                            GdkEventCrossing *gdk_event,
                            wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return FALSE;
+    if ( !wxGtkCallbackCommonPrologue(gdk_event, win) )
+        return FALSE;
 
     // Event was emitted after a grab
     if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
 
-    if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
-
     int x = 0;
     int y = 0;
     GdkModifierType state = (GdkModifierType)0;
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "leave_notify_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_leave_callback( GtkWidget *widget,
                            GdkEventCrossing *gdk_event,
                            wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return FALSE;
+    if ( !wxGtkCallbackCommonPrologue(gdk_event, win) )
+        return FALSE;
 
     // Event was emitted after an ungrab
     if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
 
-    if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
-
     wxMouseEvent event( wxEVT_LEAVE_WINDOW );
     event.SetTimestamp( gdk_event->time );
     event.SetEventObject( win );
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "value_changed" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static void
 gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
 {
         win->m_blockValueChanged[dir] = false;
     }
 }
-}
 
 //-----------------------------------------------------------------------------
 // "button_press_event" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win)
 {
 
     return false;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "event_after" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static void
 gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
 {
         win->GetEventHandler()->ProcessEvent(event);
     }
 }
-}
 
 //-----------------------------------------------------------------------------
 // "button_release_event" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* win)
 {
 
     return false;
 }
-}
-
-// ----------------------------------------------------------------------------
-// this wxWindowBase function is implemented here (in platform-specific file)
-// because it is static and so couldn't be made virtual
-// ----------------------------------------------------------------------------
-
-wxWindow *wxWindowBase::DoFindFocus()
-{
-    // the cast is necessary when we compile in wxUniversal mode
-    return (wxWindow *)g_focusWindow;
-}
 
 //-----------------------------------------------------------------------------
 // "realize" from m_widget
 /* We cannot set colours and fonts before the widget has
    been realized, so we do this directly after realization. */
 
-extern "C" {
 static void
 gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 {
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
 }
-}
 
 //-----------------------------------------------------------------------------
 // "size_allocate"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static
 void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
                                GtkAllocation *WXUNUSED(alloc),
         win->GetEventHandler()->ProcessEvent( event );
     }
 }
-}
 
 
 #ifdef HAVE_XIM
 #endif
 
 /* Resize XIM window */
-
-extern "C" {
 static
 void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
                                  GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
     }
 #endif // HAVE_XIM
 }
-}
 
 //-----------------------------------------------------------------------------
 // "realize" from m_wxwindow
 
 /* Initialize XIM support */
 
-extern "C" {
 static void
 gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
                                 wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
       }
 #endif // HAVE_XIM
 }
+
+} // extern "C"
+
+// ----------------------------------------------------------------------------
+// this wxWindowBase function is implemented here (in platform-specific file)
+// because it is static and so couldn't be made virtual
+// ----------------------------------------------------------------------------
+
+wxWindow *wxWindowBase::DoFindFocus()
+{
+    // the cast is necessary when we compile in wxUniversal mode
+    return (wxWindow *)g_focusWindow;
 }
 
 //-----------------------------------------------------------------------------
     g_object_unref (layout);
 }
 
+bool wxWindowGTK::GTKSetDelayedFocusIfNeeded()
+{
+    if ( g_delayedFocus == this )
+    {
+        if ( GTK_WIDGET_REALIZED(m_widget) )
+        {
+            gtk_widget_grab_focus(m_widget);
+            g_delayedFocus = NULL;
+
+            return true;
+        }
+    }
+
+    return false;
+}
+
 void wxWindowGTK::SetFocus()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    if (cursor == wxNullCursor)
-       return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
-    else
-       return wxWindowBase::SetCursor( cursor );
+    return wxWindowBase::SetCursor( cursor.Ok() ? cursor : *wxSTANDARD_CURSOR );
+}
+
+void wxWindowGTK::GTKUpdateCursor()
+{
+    wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
+    if ( cursor.Ok() )
+    {
+        wxArrayGdkWindows windowsThis;
+        GdkWindow * const winThis = GTKGetWindow(windowsThis);
+        if ( winThis )
+        {
+            gdk_window_set_cursor(winThis, cursor.GetCursor());
+        }
+        else
+        {
+            const size_t count = windowsThis.size();
+            for ( size_t n = 0; n < count; n++ )
+            {
+                gdk_window_set_cursor(windowsThis[n], cursor.GetCursor());
+            }
+        }
+    }
 }
 
 void wxWindowGTK::WarpPointer( int x, int y )
     return connect_widget;
 }
 
-bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window )
+bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const
 {
-    if (m_wxwindow)
-        return (window == GTK_PIZZA(m_wxwindow)->bin_window);
+    wxArrayGdkWindows windowsThis;
+    GdkWindow * const winThis = GTKGetWindow(windowsThis);
 
-    return (window == m_widget->window);
+    return winThis ? window == winThis
+                   : windowsThis.Index(window) != wxNOT_FOUND;
+}
+
+GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
+{
+    return m_wxwindow ? GTK_PIZZA(m_wxwindow)->bin_window : m_widget->window;
 }
 
 bool wxWindowGTK::SetFont( const wxFont &font )