]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
tweaks
[wxWidgets.git] / src / gtk / window.cpp
index a73310396d67df6e4d78d4fc9571f328e8fd9465..abd0171fe187c669ab565c4c1ab1ff07aafa9f93 100644 (file)
     #include "wx/layout.h"
     #include "wx/statusbr.h"
     #include "wx/math.h"
+    #include "wx/module.h"
 #endif
 
-#include "wx/module.h"
-
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
 #endif
@@ -79,8 +78,6 @@
     #undef HAVE_XIM
 #endif
 
-extern GtkContainerClass *pizza_parent_class;
-
 //-----------------------------------------------------------------------------
 // documentation on internals
 //-----------------------------------------------------------------------------
@@ -219,8 +216,6 @@ extern bool       g_blockEventsOnDrag;
 extern bool       g_blockEventsOnScroll;
 extern wxCursor   g_globalCursor;
 
-static GdkGC *g_eraseGC = NULL;
-
 // mouse capture state: the window which has it and if the mouse is currently
 // inside it
 static wxWindowGTK  *g_captureWindow = (wxWindowGTK*) NULL;
@@ -407,13 +402,9 @@ gtk_window_own_expose_callback( GtkWidget *widget,
                                 GdkEventExpose *gdk_event,
                                 wxWindowGTK *win )
 {
-    if (gdk_event->count > 0) return FALSE;
-
-    draw_frame( widget, win );
-
-    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-
-    return TRUE;
+    if (gdk_event->count == 0)
+        draw_frame(widget, win);
+    return false;
 }
 }
 
@@ -480,8 +471,7 @@ gtk_window_expose_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     // This callback gets called in drawing-idle time under
     // GTK 2.0, so we don't need to defer anything to idle
@@ -490,6 +480,7 @@ gtk_window_expose_callback( GtkWidget *widget,
     GtkPizza *pizza = GTK_PIZZA( widget );
     if (gdk_event->window != pizza->bin_window) return FALSE;
 
+
 #if 0
     if (win->GetName())
     {
@@ -519,10 +510,7 @@ gtk_window_expose_callback( GtkWidget *widget,
 
     win->GtkSendPaintEvents();
 
-
     // Let parent window draw window-less widgets
-    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-
     return FALSE;
 }
 }
@@ -991,8 +979,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     if (!win->m_hasVMT)
         return FALSE;
@@ -1124,10 +1111,6 @@ gtk_window_key_press_callback( GtkWidget *widget,
         }
     }
 
-
-
-
-
     // win is a control: tab can be propagated up
     if ( !ret &&
          ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
@@ -1152,50 +1135,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
         ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
     }
 
-    // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
-    if ( !ret &&
-         (gdk_event->keyval == GDK_Escape) )
-    {
-        // however only do it if we have a Cancel button in the dialog,
-        // otherwise the user code may get confused by the events from a
-        // nonexistent button and, worse, a wxButton might get button event
-        // from another button which is not really expected
-        wxWindow *winForCancel = win,
-                 *btnCancel = NULL;
-        while ( winForCancel )
-        {
-            btnCancel = winForCancel->FindWindow(wxID_CANCEL);
-            if ( btnCancel )
-            {
-                // found a cancel button
-                break;
-            }
-
-            if ( winForCancel->IsTopLevel() )
-            {
-                // no need to look further
-                break;
-            }
-
-            // maybe our parent has a cancel button?
-            winForCancel = winForCancel->GetParent();
-        }
-
-        if ( btnCancel )
-        {
-            wxCommandEvent eventClick(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
-            eventClick.SetEventObject(btnCancel);
-            ret = btnCancel->GetEventHandler()->ProcessEvent(eventClick);
-        }
-    }
-
-    if (ret)
-    {
-        g_signal_stop_emission_by_name (widget, "key_press_event");
-        return TRUE;
-    }
-
-    return FALSE;
+    return ret;
 }
 }
 
@@ -1281,8 +1221,7 @@ gtk_window_key_release_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     if (!win->m_hasVMT)
         return FALSE;
@@ -1297,11 +1236,7 @@ gtk_window_key_release_callback( GtkWidget *widget,
         return FALSE;
     }
 
-    if ( !win->GetEventHandler()->ProcessEvent( event ) )
-        return FALSE;
-
-    g_signal_stop_emission_by_name (widget, "key_release_event");
-    return TRUE;
+    return win->GTKProcessEvent(event);
 }
 }
 
@@ -1339,6 +1274,13 @@ template<typename T> void InitMouseEvent(wxWindowGTK *win,
     wxPoint pt = win->GetClientAreaOrigin();
     event.m_x = (wxCoord)gdk_event->x - pt.x;
     event.m_y = (wxCoord)gdk_event->y - pt.y;
+    
+    if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft))
+    {
+        // origin in the upper right corner
+        int window_width = gtk_pizza_get_rtl_offset( GTK_PIZZA(win->m_wxwindow) );
+        event.m_x = window_width - event.m_x;
+    }
 
     event.SetEventObject( win );
     event.SetId( win->GetId() );
@@ -1387,8 +1329,8 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
     if (win->m_wxwindow)
     {
         GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
-        xx += pizza->xoffset;
-        yy += pizza->yoffset;
+        xx += gtk_pizza_get_xoffset( pizza );
+        yy += gtk_pizza_get_yoffset( pizza );
     }
 
     wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
@@ -1443,42 +1385,88 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
     return win;
 }
 
+// ----------------------------------------------------------------------------
+// common event handlers helpers
+// ----------------------------------------------------------------------------
+
+bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const
+{
+    // nothing special at this level
+    return GetEventHandler()->ProcessEvent(event);
+}
+
+int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
+{
+    DEBUG_MAIN_THREAD
+
+    // don't need to install idle handler, its done from "event" signal
+
+    if (!m_hasVMT)
+        return FALSE;
+    if (g_blockEventsOnDrag)
+        return TRUE;
+    if (g_blockEventsOnScroll)
+        return TRUE;
+
+    if (!GTKIsOwnWindow(event->window))
+        return FALSE;
+
+    return -1;
+}
+
+// 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 int 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
+
+#define wxCOMMON_CALLBACK_PROLOGUE(event, win)                                \
+    const int rc = wxGtkCallbackCommonPrologue(event, win);                   \
+    if ( rc != -1 )                                                           \
+        return rc
+
+// 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;
+    wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     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
@@ -1611,9 +1599,8 @@ gtk_window_button_press_callback( GtkWidget *widget,
     event.SetEventObject( win );
     event.SetId( win->GetId() );
 
-    if (win->GetEventHandler()->ProcessEvent( event ))
+    if (win->GTKProcessEvent( event ))
     {
-        g_signal_stop_emission_by_name (widget, "button_press_event");
         return TRUE;
     }
 
@@ -1631,33 +1618,22 @@ gtk_window_button_press_callback( GtkWidget *widget,
             win->GetId(),
             win->ClientToScreen(event.GetPosition()));
         evtCtx.SetEventObject(win);
-        return win->GetEventHandler()->ProcessEvent(evtCtx);
+        return win->GTKProcessEvent(evtCtx);
     }
 
     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;
+    wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     wxEventType event_type = wxEVT_NULL;
 
@@ -1695,36 +1671,19 @@ gtk_window_button_release_callback( GtkWidget *widget,
     event.SetEventObject( win );
     event.SetId( win->GetId() );
 
-    if (win->GetEventHandler()->ProcessEvent( event ))
-    {
-        g_signal_stop_emission_by_name (widget, "button_release_event");
-        return TRUE;
-    }
-
-    return FALSE;
-}
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
 // "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;
+    wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     if (gdk_event->is_hint)
     {
@@ -1736,13 +1695,6 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
         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);
 
@@ -1764,7 +1716,7 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
                                                         : wxEVT_LEAVE_WINDOW);
             InitMouseEvent(win, eventM, gdk_event);
             eventM.SetEventObject(win);
-            win->GetEventHandler()->ProcessEvent(eventM);
+            win->GTKProcessEvent(eventM);
         }
     }
     else // no capture
@@ -1779,34 +1731,25 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
     if ( !g_captureWindow )
     {
         wxSetCursorEvent cevent( event.m_x, event.m_y );
-        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        if (win->GTKProcessEvent( cevent ))
         {
-            // Rewrite cursor handling here (away from idle).
+            win->SetCursor( cevent.GetCursor() );
         }
     }
 
-    if (win->GetEventHandler()->ProcessEvent( event ))
-    {
-        g_signal_stop_emission_by_name (widget, "motion_notify_event");
-        return TRUE;
-    }
-
-    return FALSE;
-}
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
 // "scroll_event", (mouse wheel event)
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     if (gdk_event->direction != GDK_SCROLL_UP &&
         gdk_event->direction != GDK_SCROLL_DOWN)
@@ -1839,45 +1782,24 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
     event.SetId( win->GetId() );
     event.SetTimestamp( gdk_event->time );
 
-    return win->GetEventHandler()->ProcessEvent(event);
-}
+    return win->GTKProcessEvent(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);
-}
+    return win->GTKProcessEvent(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),
@@ -1885,8 +1807,7 @@ gtk_window_focus_in_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     if (win->m_imData)
         gtk_im_context_focus_in(win->m_imData->context);
@@ -1931,13 +1852,11 @@ gtk_window_focus_in_callback( GtkWidget *widget,
 
     return FALSE;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "focus_out_event"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_window_focus_out_callback( GtkWidget *widget,
                                GdkEventFocus *gdk_event,
@@ -1945,8 +1864,7 @@ gtk_window_focus_out_callback( GtkWidget *widget,
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     if (win->m_imData)
         gtk_im_context_focus_out(win->m_imData->context);
@@ -1986,7 +1904,7 @@ gtk_window_focus_out_callback( GtkWidget *widget,
         wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
         event.SetEventObject( win );
 
-        (void)win->GetEventHandler()->ProcessEvent( event );
+        (void)win->GTKProcessEvent( event );
 
         ret = TRUE;
     }
@@ -1998,31 +1916,21 @@ gtk_window_focus_out_callback( GtkWidget *widget,
 
     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;
+    wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     // 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;
@@ -2038,45 +1946,29 @@ gtk_window_enter_callback( GtkWidget *widget,
     if ( !g_captureWindow )
     {
         wxSetCursorEvent cevent( event.m_x, event.m_y );
-        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        if (win->GTKProcessEvent( cevent ))
         {
-            // Rewrite cursor handling here (away from idle).
+            win->SetCursor( cevent.GetCursor() );
         }
     }
 
-    if (win->GetEventHandler()->ProcessEvent( event ))
-    {
-       g_signal_stop_emission_by_name (widget, "enter_notify_event");
-       return TRUE;
-    }
-
-    return FALSE;
-}
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
 // "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;
+    wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     // 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 );
@@ -2099,21 +1991,13 @@ gtk_window_leave_callback( GtkWidget *widget,
     event.m_x = x + pt.x;
     event.m_y = y + pt.y;
 
-    if (win->GetEventHandler()->ProcessEvent( event ))
-    {
-        g_signal_stop_emission_by_name (widget, "leave_notify_event");
-        return TRUE;
-    }
-
-    return FALSE;
-}
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
 // "value_changed" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static void
 gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
 {
@@ -2122,42 +2006,42 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
     {
         // Convert scroll event type to scrollwin event type
         eventType += wxEVT_SCROLLWIN_TOP - wxEVT_SCROLL_TOP;
-        const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL;
-        const int i = orient == wxVERTICAL;
+
+        // find the scrollbar which generated the event
+        wxWindowGTK::ScrollDir dir = win->ScrollDirFromRange(range);
+
+        // generate the corresponding wx event
+        const int orient = win->OrientFromScrollDir(dir);
         wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient);
         event.SetEventObject(win);
-        win->m_blockValueChanged[i] = true;
-        win->GetEventHandler()->ProcessEvent(event);
-        win->m_blockValueChanged[i] = false;
+
+        win->m_blockValueChanged[dir] = true;
+        win->GTKProcessEvent(event);
+        win->m_blockValueChanged[dir] = false;
     }
 }
-}
 
 //-----------------------------------------------------------------------------
 // "button_press_event" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win)
 {
     DEBUG_MAIN_THREAD
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    // don't need to install idle handler, its done from "event" signal
 
     g_blockEventsOnScroll = true;
     win->m_mouseButtonDown = true;
 
     return false;
 }
-}
 
 //-----------------------------------------------------------------------------
 // "event_after" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static void
 gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
 {
@@ -2165,19 +2049,18 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
     {
         g_signal_handlers_block_by_func(range, (void*)gtk_scrollbar_event_after, win);
 
-        const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL;
+        const int orient = win->OrientFromScrollDir(
+                                        win->ScrollDirFromRange(range));
         wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
         event.SetEventObject(win);
-        win->GetEventHandler()->ProcessEvent(event);
+        win->GTKProcessEvent(event);
     }
 }
-}
 
 //-----------------------------------------------------------------------------
 // "button_release_event" from scrollbar
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static gboolean
 gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* win)
 {
@@ -2197,18 +2080,6 @@ gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* w
 
     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
@@ -2217,7 +2088,6 @@ wxWindow *wxWindowBase::DoFindFocus()
 /* 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 )
 {
@@ -2235,18 +2105,16 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
-}
+    win->GTKProcessEvent( event );
 }
 
 //-----------------------------------------------------------------------------
 // "size_allocate"
 //-----------------------------------------------------------------------------
 
-extern "C" {
 static
 void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
-                               GtkAllocation *WXUNUSED(alloc),
+                               GtkAllocation *alloc,
                                wxWindow *win )
 {
     if (g_isIdle)
@@ -2258,6 +2126,19 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
     if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
         return;
 
+#if 0
+        wxPrintf( wxT("size_allocate ") );
+        if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+            wxPrintf( win->GetClassInfo()->GetClassName() );
+        wxPrintf( wxT(" %d %d %d %d\n"),
+                alloc->x,
+                alloc->y,
+                alloc->width,
+                alloc->height );
+#endif
+                
+    GTK_PIZZA(win->m_wxwindow)->m_width = win->GetClientSize().x;
+
     win->m_oldClientWidth = client_width;
     win->m_oldClientHeight = client_height;
 
@@ -2265,10 +2146,9 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
     {
         wxSizeEvent event( win->GetSize(), win->GetId() );
         event.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent( event );
+        win->GTKProcessEvent( event );
     }
 }
-}
 
 
 #ifdef HAVE_XIM
@@ -2278,8 +2158,6 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
 #endif
 
 /* Resize XIM window */
-
-extern "C" {
 static
 void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
                                  GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
@@ -2303,7 +2181,6 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
     }
 #endif // HAVE_XIM
 }
-}
 
 //-----------------------------------------------------------------------------
 // "realize" from m_wxwindow
@@ -2311,7 +2188,6 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
 
 /* Initialize XIM support */
 
-extern "C" {
 static void
 gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
                                 wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
@@ -2396,6 +2272,18 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
       }
 #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;
 }
 
 //-----------------------------------------------------------------------------
@@ -2414,8 +2302,8 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
     /* the window might have been scrolled already, do we
        have to adapt the position */
     GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
-    child->m_x += pizza->xoffset;
-    child->m_y += pizza->yoffset;
+    child->m_x += gtk_pizza_get_xoffset( pizza );
+    child->m_y += gtk_pizza_get_yoffset( pizza );
 
     gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
                      GTK_WIDGET(child->m_widget),
@@ -2489,6 +2377,8 @@ void wxWindowGTK::Init()
     m_needParent = true;
     m_isBeingDeleted = false;
 
+    m_showOnIdle= false;
+
     m_noExpose = false;
     m_nativeSizeEvent = false;
 
@@ -2497,12 +2387,13 @@ void wxWindowGTK::Init()
     m_mouseButtonDown = false;
     m_blockScrollEvent = false;
 
-    m_scrollBar[0] =
-    m_scrollBar[1] = NULL;
-    m_scrollPos[0] =
-    m_scrollPos[1] = 0;
-    m_blockValueChanged[0] =
-    m_blockValueChanged[1] = false;
+    // initialize scrolling stuff
+    for ( int dir = 0; dir < ScrollDir_Max; dir++ )
+    {
+        m_scrollBar[dir] = NULL;
+        m_scrollPos[dir] = 0;
+        m_blockValueChanged[dir] = false;
+    }
 
     m_oldClientWidth =
     m_oldClientHeight = 0;
@@ -2567,14 +2458,14 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
     gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
 
-    m_scrollBar[0] = GTK_RANGE(scrolledWindow->hscrollbar);
-    m_scrollBar[1] = GTK_RANGE(scrolledWindow->vscrollbar);
+    m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar);
+    m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar);
 
     m_wxwindow = gtk_pizza_new();
 
 #ifndef __WXUNIVERSAL__
     GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
-
+    
     if (HasFlag(wxRAISED_BORDER))
     {
         gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
@@ -2598,31 +2489,25 @@ bool wxWindowGTK::Create( wxWindow *parent,
     GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
     m_acceptsFocus = true;
 
-    // these handlers block mouse events to any window during scrolling such as
-    // motion events and prevent GTK and wxWidgets from fighting over where the
-    // slider should be
-    g_signal_connect(m_scrollBar[0], "button_press_event",
-                     G_CALLBACK(gtk_scrollbar_button_press_event), this);
-    g_signal_connect(m_scrollBar[1], "button_press_event",
-                     G_CALLBACK(gtk_scrollbar_button_press_event), this);
-    g_signal_connect(m_scrollBar[0], "button_release_event",
-                     G_CALLBACK(gtk_scrollbar_button_release_event), this);
-    g_signal_connect(m_scrollBar[1], "button_release_event",
-                     G_CALLBACK(gtk_scrollbar_button_release_event), this);
-    gulong handler_id;
-    handler_id = g_signal_connect(
-        m_scrollBar[0], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this);
-    g_signal_handler_block(m_scrollBar[0], handler_id);
-    handler_id = g_signal_connect(
-        m_scrollBar[1], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this);
-    g_signal_handler_block(m_scrollBar[1], handler_id);
-
-    // these handlers get notified when scrollbar slider moves
-
-    g_signal_connect(m_scrollBar[0], "value_changed",
-                     G_CALLBACK(gtk_scrollbar_value_changed), this);
-    g_signal_connect(m_scrollBar[1], "value_changed",
-                     G_CALLBACK(gtk_scrollbar_value_changed), this);
+    // connect various scroll-related events
+    for ( int dir = 0; dir < ScrollDir_Max; dir++ )
+    {
+        // these handlers block mouse events to any window during scrolling
+        // such as motion events and prevent GTK and wxWidgets from fighting
+        // over where the slider should be
+        g_signal_connect(m_scrollBar[dir], "button_press_event",
+                         G_CALLBACK(gtk_scrollbar_button_press_event), this);
+        g_signal_connect(m_scrollBar[dir], "button_release_event",
+                         G_CALLBACK(gtk_scrollbar_button_release_event), this);
+
+        gulong handler_id = g_signal_connect(m_scrollBar[dir], "event_after",
+                                G_CALLBACK(gtk_scrollbar_event_after), this);
+        g_signal_handler_block(m_scrollBar[dir], handler_id);
+
+        // these handlers get notified when scrollbar slider moves
+        g_signal_connect(m_scrollBar[dir], "value_changed",
+                         G_CALLBACK(gtk_scrollbar_value_changed), this);
+    }
 
     gtk_widget_show( m_wxwindow );
 
@@ -2715,12 +2600,11 @@ void wxWindowGTK::PostCreation()
         {
             // these get reported to wxWidgets -> wxPaintEvent
 
-            gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
-
             g_signal_connect (m_wxwindow, "expose_event",
                               G_CALLBACK (gtk_window_expose_callback), this);
 
-            gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
+            if (GetLayoutDirection() == wxLayout_LeftToRight)
+                gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
         }
 
         // Create input method handler
@@ -2795,7 +2679,7 @@ void wxWindowGTK::PostCreation()
                           this);
     }
 #ifdef GTK_IS_FILE_CHOOSER_BUTTON
-    else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
+    else 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
@@ -2818,6 +2702,8 @@ void wxWindowGTK::PostCreation()
 
     m_hasVMT = true;
 
+    SetLayoutDirection(wxLayout_Default);
+
     // unless the window was created initially hidden (i.e. Hide() had been
     // called before Create()), we should show it at GTK+ level as well
     if ( IsShown() )
@@ -2857,7 +2743,9 @@ bool wxWindowGTK::Destroy()
 
 void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
 {
+    // inform the parent to perform the move
     gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
+    
 }
 
 void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
@@ -2865,10 +2753,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
     wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") );
 
-/*
-    printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
-*/
-
     if (m_resizing) return; /* I don't like recursions */
     m_resizing = true;
 
@@ -2912,8 +2796,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
        // don't take the x,y values, they're wrong because toolbar sets them
        GtkWidget  *widget = GTK_WIDGET(m_widget);
        gtk_widget_set_size_request (widget, m_width, m_height);
-       if (GTK_WIDGET_VISIBLE (widget))
-            gtk_widget_queue_resize (widget);
     }
     else
 #endif
@@ -2930,13 +2812,13 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
         if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
         {
-            if (x != -1) m_x = x + pizza->xoffset;
-            if (y != -1) m_y = y + pizza->yoffset;
+            if (x != -1) m_x = x + gtk_pizza_get_xoffset( pizza );
+            if (y != -1) m_y = y + gtk_pizza_get_yoffset( pizza );
         }
         else
         {
-            m_x = x + pizza->xoffset;
-            m_y = y + pizza->yoffset;
+            m_x = x + gtk_pizza_get_xoffset( pizza );
+            m_y = y + gtk_pizza_get_yoffset( pizza );
         }
 
         int left_border = 0;
@@ -2993,8 +2875,32 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
     m_resizing = false;
 }
 
+bool wxWindowGTK::GtkShowFromOnIdle()
+{
+    if (IsShown() && m_showOnIdle && !GTK_WIDGET_VISIBLE (m_widget))
+    {
+        GtkAllocation alloc;
+        alloc.x = m_x;
+        alloc.y = m_y;
+        alloc.width = m_width;
+        alloc.height = m_height;
+        gtk_widget_size_allocate( m_widget, &alloc );
+        gtk_widget_show( m_widget );
+        wxShowEvent eventShow(GetId(), true);
+        eventShow.SetEventObject(this);
+        GetEventHandler()->ProcessEvent(eventShow);
+        m_showOnIdle = false;
+        return true;
+    }
+
+    return false;
+}
+
 void wxWindowGTK::OnInternalIdle()
 {
+    // Check if we have to show window now
+    if (GtkShowFromOnIdle()) return;
+
     if ( m_dirtyTabOrder )
     {
         m_dirtyTabOrder = false;
@@ -3009,9 +2915,6 @@ void wxWindowGTK::OnInternalIdle()
         m_needsStyleChange = false;
     }
 
-    // Update invalidated regions.
-    GtkUpdate();
-
     wxCursor cursor = m_cursor;
     if (g_globalCursor.Ok()) cursor = g_globalCursor;
 
@@ -3036,13 +2939,11 @@ void wxWindowGTK::OnInternalIdle()
                 gdk_window_set_cursor( window, cursor.GetCursor() );
 
         }
-        else
+        else if ( m_widget )
         {
-
             GdkWindow *window = m_widget->window;
-            if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
+            if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) )
                gdk_window_set_cursor( window, cursor.GetCursor() );
-
         }
     }
 
@@ -3128,6 +3029,10 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
 
         w -= dw;
         h -= dh;
+        if (w < 0)
+            w = 0;
+        if (h < 0)
+            h = 0;
     }
 
     if (width) *width = w;
@@ -3143,8 +3048,30 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
     if (m_parent && m_parent->m_wxwindow)
     {
         GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
-        dx = pizza->xoffset;
-        dy = pizza->yoffset;
+        dx = gtk_pizza_get_xoffset( pizza );
+        dy = gtk_pizza_get_yoffset( pizza );
+    }
+
+    if (m_x == -1 && m_y == -1)
+    {
+        GdkWindow *source = (GdkWindow *) NULL;
+        if (m_wxwindow)
+            source = GTK_PIZZA(m_wxwindow)->bin_window;
+        else
+            source = m_widget->window;
+
+        if (source)
+        {
+            int org_x = 0;
+            int org_y = 0;
+            gdk_window_get_origin( source, &org_x, &org_y );
+
+            if (GetParent())
+                GetParent()->ScreenToClient(&org_x, &org_y);
+
+            ((wxWindowGTK*) this)->m_x = org_x;
+            ((wxWindowGTK*) this)->m_y = org_y;
+       }
     }
 
     if (x) (*x) = m_x - dx;
@@ -3176,7 +3103,15 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const
         }
     }
 
-    if (x) *x += org_x;
+
+    if (x)
+    {
+        if (GetLayoutDirection() == wxLayout_RightToLeft)
+            *x = (GetClientSize().x - *x) + org_x;
+        else 
+            *x += org_x;
+    }
+    
     if (y) *y += org_y;
 }
 
@@ -3205,7 +3140,13 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
         }
     }
 
-    if (x) *x -= org_x;
+    if (x)
+    {
+        if (GetLayoutDirection() == wxLayout_RightToLeft)
+            *x = (GetClientSize().x - *x) - org_x;
+        else 
+            *x -= org_x;
+    }
     if (y) *y -= org_y;
 }
 
@@ -3220,14 +3161,22 @@ bool wxWindowGTK::Show( bool show )
     }
 
     if (show)
-        gtk_widget_show( m_widget );
+    {
+        if (!m_showOnIdle)
+        {
+            gtk_widget_show( m_widget );
+            wxShowEvent eventShow(GetId(), show);
+            eventShow.SetEventObject(this);
+            GetEventHandler()->ProcessEvent(eventShow);
+        }
+    }
     else
+    {
         gtk_widget_hide( m_widget );
-
-    wxShowEvent eventShow(GetId(), show);
-    eventShow.SetEventObject(this);
-
-    GetEventHandler()->ProcessEvent(eventShow);
+        wxShowEvent eventShow(GetId(), show);
+        eventShow.SetEventObject(this);
+        GetEventHandler()->ProcessEvent(eventShow);
+    }
 
     return true;
 }
@@ -3379,6 +3328,22 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
     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") );
@@ -3465,6 +3430,12 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
 
     if (newParent)
     {
+        if (GTK_WIDGET_VISIBLE (newParent->m_widget))
+        {
+            m_showOnIdle = true;
+            gtk_widget_hide( m_widget );
+        }
+
         /* insert GTK representation */
         (*(newParent->m_insertCallback))(newParent, this);
     }
@@ -3472,6 +3443,8 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
     /* reverse: prevent GTK from deleting the widget arbitrarily */
     gtk_widget_unref( m_widget );
 
+    SetLayoutDirection(wxLayout_Default);
+
     return true;
 }
 
@@ -3506,6 +3479,63 @@ void wxWindowGTK::RemoveChild(wxWindowBase *child)
         wxapp_install_idle_handler();
 }
 
+/* static */
+wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget)
+{
+    return gtk_widget_get_direction(GTK_WIDGET(widget)) == GTK_TEXT_DIR_RTL
+                ? wxLayout_RightToLeft
+                : wxLayout_LeftToRight;
+}
+
+/* static */
+void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir)
+{
+    wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") );
+
+    gtk_widget_set_direction(GTK_WIDGET(widget),
+                             dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL
+                                                         : GTK_TEXT_DIR_LTR);
+}
+
+wxLayoutDirection wxWindowGTK::GetLayoutDirection() const
+{
+    return GTKGetLayout(m_widget);
+}
+
+void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir)
+{
+    if ( dir == wxLayout_Default )
+    {
+        const wxWindow *const parent = GetParent();
+        if ( parent )
+        {
+            // inherit layout from parent.
+            dir = parent->GetLayoutDirection();
+        }
+        else // no parent, use global default layout
+        {
+            dir = wxTheApp->GetLayoutDirection();
+        }
+    }
+
+    if ( dir == wxLayout_Default )
+        return;
+
+    GTKSetLayout(m_widget, dir);
+    
+    if (m_wxwindow)
+        GTKSetLayout(m_wxwindow, dir);
+}
+
+wxCoord
+wxWindowGTK::AdjustForLayoutDirection(wxCoord x,
+                                      wxCoord WXUNUSED(width),
+                                      wxCoord WXUNUSED(widthTotal)) const
+{
+    // We now mirrors the coordinates of RTL windows in GtkPizza
+    return x;
+}
+
 void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
 {
     wxWindowBase::DoMoveInTabOrder(win, move);
@@ -3616,18 +3646,41 @@ void wxWindowGTK::Lower()
 
 bool wxWindowGTK::SetCursor( const wxCursor &cursor )
 {
-    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
+    if ( !wxWindowBase::SetCursor(cursor.Ok() ? cursor : *wxSTANDARD_CURSOR) )
+        return false;
 
-    if (cursor == m_cursor)
-       return false;
+    GTKUpdateCursor();
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    return true;
+}
 
-    if (cursor == wxNullCursor)
-       return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
-    else
-       return wxWindowBase::SetCursor( 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++ )
+            {
+                GdkWindow *win = windowsThis[n];
+                if ( !win )
+                {
+                    wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?"));
+                    continue;
+                }
+
+                gdk_window_set_cursor(win, cursor.GetCursor());
+            }
+        }
+    }
 }
 
 void wxWindowGTK::WarpPointer( int x, int y )
@@ -3647,34 +3700,49 @@ void wxWindowGTK::WarpPointer( int x, int y )
         gdk_window_warp_pointer( window, x, y );
 }
 
-bool wxWindowGTK::ScrollLines(int lines)
+wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const
 {
-    bool changed = false;
-    GtkRange* range = m_scrollBar[1];
-    if (range != NULL)
+    // find the scrollbar which generated the event
+    for ( int dir = 0; dir < ScrollDir_Max; dir++ )
     {
-        GtkAdjustment* adj = range->adjustment;
-        const int pos = int(adj->value + 0.5);
-        gtk_range_set_value(range, pos + lines);
-        changed = pos != int(adj->value + 0.5);
+        if ( range == m_scrollBar[dir] )
+            return (ScrollDir)dir;
     }
-    return changed;
+
+    wxFAIL_MSG( _T("event from unknown scrollbar received") );
+
+    return ScrollDir_Max;
 }
 
-bool wxWindowGTK::ScrollPages(int pages)
+bool wxWindowGTK::DoScrollByUnits(ScrollDir dir, ScrollUnit unit, int units)
 {
     bool changed = false;
-    GtkRange* range = m_scrollBar[1];
-    if (range != NULL)
+    GtkRange* range = m_scrollBar[dir];
+    if ( range && units )
     {
         GtkAdjustment* adj = range->adjustment;
-        const int pos = int(adj->value + 0.5);
-        gtk_range_set_value(range, pos + pages * adj->page_size);
-        changed = pos != int(adj->value + 0.5);
+        gdouble inc = unit == ScrollUnit_Line ? adj->step_increment
+                                              : adj->page_increment;
+
+        const int posOld = int(adj->value + 0.5);
+        gtk_range_set_value(range, posOld + units*inc);
+
+        changed = int(adj->value + 0.5) != posOld;
     }
+
     return changed;
 }
 
+bool wxWindowGTK::ScrollLines(int lines)
+{
+    return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Line, lines);
+}
+
+bool wxWindowGTK::ScrollPages(int pages)
+{
+    return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Page, pages);
+}
+
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
     if (!m_widget)
@@ -3684,6 +3752,8 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 
     if (m_wxwindow)
     {
+        if (!GTK_PIZZA(m_wxwindow)->bin_window) return;
+
         GdkRectangle gdk_rect,
                     *p;
         if (rect)
@@ -3692,13 +3762,15 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
             gdk_rect.y = rect->y;
             gdk_rect.width = rect->width;
             gdk_rect.height = rect->height;
+            if (GetLayoutDirection() == wxLayout_RightToLeft)
+                gdk_rect.x = GetClientSize().x - gdk_rect.x - gdk_rect.width;
             p = &gdk_rect;
         }
         else // invalidate everything
         {
             p = NULL;
         }
-
+        
         gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
     }
 }
@@ -3718,6 +3790,8 @@ void wxWindowGTK::GtkUpdate()
 {
     if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
         gdk_window_process_updates( GTK_PIZZA(m_wxwindow)->bin_window, FALSE );
+    if (m_widget && m_widget->window)
+        gdk_window_process_updates( m_widget->window, FALSE );
 
     // for consistency with other platforms (and also because it's convenient
     // to be able to update an entire TLW by calling Update() only once), we
@@ -3730,6 +3804,20 @@ void wxWindowGTK::GtkUpdate()
     }
 }
 
+bool wxWindowGTK::DoIsExposed( int x, int y ) const
+{
+    return m_updateRegion.Contains(x, y) != wxOutRegion;
+}
+
+
+bool wxWindowGTK::DoIsExposed( int x, int y, int w, int h ) const
+{
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+        return m_updateRegion.Contains(x-w, y, w, h) != wxOutRegion;
+    else
+        return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
+}
+
 void wxWindowGTK::GtkSendPaintEvents()
 {
     if (!m_wxwindow)
@@ -3741,6 +3829,34 @@ void wxWindowGTK::GtkSendPaintEvents()
     // Clip to paint region in wxClientDC
     m_clipPaintRegion = true;
 
+    wxRegion maybe_rtl_region = m_updateRegion;
+    
+#if 0
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+    {
+        maybe_rtl_region.Clear();
+        
+        gint width;
+        gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window,
+                                 NULL, NULL, &width, NULL, NULL );
+        
+        wxRegionIterator upd( m_updateRegion );
+        while (upd)
+        {
+            wxRect rect;
+            rect.x = upd.GetX();
+            rect.y = upd.GetY();
+            rect.width = upd.GetWidth();
+            rect.height = upd.GetHeight();
+            
+            rect.x = width - rect.x - rect.width;
+            maybe_rtl_region.Union( rect );
+            
+            ++upd;
+        }
+    }
+#endif
+    
     // widget to draw on
     GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
 
@@ -3776,8 +3892,9 @@ void wxWindowGTK::GtkSendPaintEvents()
         }
     }
     else
-
     {
+        m_updateRegion = maybe_rtl_region;
+    
         wxWindowDC dc( (wxWindow*)this );
         dc.SetClippingRegion( m_updateRegion );
 
@@ -3787,6 +3904,8 @@ void wxWindowGTK::GtkSendPaintEvents()
         GetEventHandler()->ProcessEvent(erase_event);
     }
 
+    m_updateRegion = maybe_rtl_region;
+        
     wxNcPaintEvent nc_paint_event( GetId() );
     nc_paint_event.SetEventObject( this );
     GetEventHandler()->ProcessEvent( nc_paint_event );
@@ -4022,12 +4141,18 @@ GtkWidget* wxWindowGTK::GetConnectWidget()
     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 winThis ? window == winThis
+                   : windowsThis.Index(window) != wxNOT_FOUND;
+}
 
-    return (window == m_widget->window);
+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 )
@@ -4116,8 +4241,11 @@ void wxWindowGTK::UnblockScrollEvent()
     m_blockScrollEvent = false;
 }
 
-void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
-      int range, bool )
+void wxWindowGTK::SetScrollbar(int orient,
+                               int pos,
+                               int thumbVisible,
+                               int range,
+                               bool WXUNUSED(update))
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
@@ -4137,8 +4265,7 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
         pos = range - thumbVisible;
     if (pos < 0)
         pos = 0;
-    const int i = orient == wxVERTICAL;
-    GtkAdjustment* adj = m_scrollBar[i]->adjustment;
+    GtkAdjustment* adj = m_scrollBar[ScrollDirFromOrient(orient)]->adjustment;
     adj->step_increment = 1;
     adj->page_increment =
     adj->page_size = thumbVisible;
@@ -4147,7 +4274,7 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
     gtk_adjustment_changed(adj);
 }
 
-void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
+void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
@@ -4156,30 +4283,29 @@ void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
     //   will not move smoothly while tracking when using wxScrollHelper.
     if (GetScrollPos(orient) != pos)
     {
-        const int i = orient == wxVERTICAL;
-        GtkAdjustment* adj = m_scrollBar[i]->adjustment;
+        const int dir = ScrollDirFromOrient(orient);
+        GtkAdjustment* adj = m_scrollBar[dir]->adjustment;
         const int max = int(adj->upper - adj->page_size);
         if (pos > max)
             pos = max;
         if (pos < 0)
             pos = 0;
-        m_scrollPos[i] =
+        m_scrollPos[dir] =
         adj->value = pos;
         // If a "value_changed" signal emission is not already in progress
-        if (!m_blockValueChanged[i])
+        if (!m_blockValueChanged[dir])
         {
             gtk_adjustment_value_changed(adj);
         }
     }
 }
 
-int wxWindowGTK::GetScrollThumb( int orient ) const
+int wxWindowGTK::GetScrollThumb(int orient) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
     wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
 
-    const int i = orient == wxVERTICAL;
-    return int(m_scrollBar[i]->adjustment->page_size);
+    return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size);
 }
 
 int wxWindowGTK::GetScrollPos( int orient ) const
@@ -4187,8 +4313,7 @@ int wxWindowGTK::GetScrollPos( int orient ) const
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
     wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
 
-    const int i = orient == wxVERTICAL;
-    return int(m_scrollBar[i]->adjustment->value + 0.5);
+    return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5);
 }
 
 int wxWindowGTK::GetScrollRange( int orient ) const
@@ -4196,8 +4321,7 @@ int wxWindowGTK::GetScrollRange( int orient ) const
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
     wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
 
-    const int i = orient == wxVERTICAL;
-    return int(m_scrollBar[i]->adjustment->upper);
+    return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper);
 }
 
 // Determine if increment is the same as +/-x, allowing for some small
@@ -4349,33 +4473,3 @@ void wxRemoveGrab(wxWindow* window)
 {
     gtk_grab_remove( (GtkWidget*) window->GetHandle() );
 }
-
-// ----------------------------------------------------------------------------
-// wxWinModule
-// ----------------------------------------------------------------------------
-
-class wxWinModule : public wxModule
-{
-public:
-    bool OnInit();
-    void OnExit();
-
-private:
-    DECLARE_DYNAMIC_CLASS(wxWinModule)
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule)
-
-bool wxWinModule::OnInit()
-{
-    // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() );
-    // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
-
-    return true;
-}
-
-void wxWinModule::OnExit()
-{
-    if (g_eraseGC)
-        g_object_unref (g_eraseGC);
-}