]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
oops, forgot to fix wxHtmlTag dtor
[wxWidgets.git] / src / gtk / window.cpp
index e138b71350cc52efc3193a2cb3e74bb3ed099071..8dfbf2b0962ba6f1ff4ac7b5b445fc45466b4b05 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        window.cpp
+// Name:        gtk/window.cpp
 // Purpose:
 // Author:      Robert Roebling
 // Id:          $Id$
     #pragma implementation "window.h"
 #endif
 
+#ifdef __VMS
+#define XWarpPointer XWARPPOINTER
+#endif
+
 #include "wx/defs.h"
 #include "wx/window.h"
-#include "wx/dc.h"
+#include "wx/dcclient.h"
 #include "wx/frame.h"
 #include "wx/app.h"
 #include "wx/layout.h"
     #include "wx/tooltip.h"
 #endif
 
+#if wxUSE_CARET
+    #include "wx/caret.h"
+#endif // wxUSE_CARET
+
 #include "wx/menu.h"
 #include "wx/statusbr.h"
 #include "wx/intl.h"
 #include <gtk/gtk.h>
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkkeysyms.h>
-#include <wx/gtk/win_gtk.h>
-
 #include <gdk/gdkx.h>
 
+#include <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
+
+#include "wx/gtk/win_gtk.h"
+
 //-----------------------------------------------------------------------------
 // documentation on internals
 //-----------------------------------------------------------------------------
@@ -188,9 +199,18 @@ extern wxList     wxPendingDelete;
 extern bool       g_blockEventsOnDrag;
 extern bool       g_blockEventsOnScroll;
 extern wxCursor   g_globalCursor;
-static wxWindow  *g_captureWindow = (wxWindow*) NULL;
 
-/* extern */ wxWindow  *g_focusWindow = (wxWindow*) NULL;
+// mouse capture state: the window which has it and if the mouse is currently
+// inside it
+static wxWindowGTK  *g_captureWindow = (wxWindowGTK*) NULL;
+static bool g_captureWindowHasMouse = FALSE;
+
+/* extern */ wxWindowGTK  *g_focusWindow = (wxWindowGTK*) NULL;
+
+// the last window which had the focus - this is normally never NULL (except
+// if we never had focus at all) as even when g_focusWindow is NULL it still
+// keeps its previous value
+static wxWindowGTK *g_focusWindowLast = (wxWindowGTK *)NULL;
 
 // if we detect that the app has got/lost the focus, we set this variable to
 // either TRUE or FALSE and an activate event will be sent during the next
@@ -208,6 +228,10 @@ extern bool g_mainThreadLocked;
 // debug
 //-----------------------------------------------------------------------------
 
+#ifndef __WXGTK20__
+#define DISABLE_STYLE_IF_BROKEN_THEME 1
+#endif
+
 #ifdef __WXDEBUG__
 
 #if wxUSE_THREADS
@@ -265,11 +289,23 @@ gdk_window_warp_pointer (GdkWindow      *window,
                          gint            x,
                          gint            y)
 {
+#ifndef __WXGTK20__
   GdkWindowPrivate *priv;
+#endif
 
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = GDK_ROOT_PARENT();
 
+#ifdef __WXGTK20__
+  if (!GDK_WINDOW_DESTROYED(window))
+  {
+      XWarpPointer (GDK_WINDOW_XDISPLAY(window),
+                    None,              /* not source window -> move from anywhere */
+                    GDK_WINDOW_XID(window),  /* dest window */
+                    0, 0, 0, 0,        /* not source window -> move from anywhere */
+                    x, y );
+  }
+#else
   priv = (GdkWindowPrivate*) window;
 
   if (!priv->destroyed)
@@ -280,6 +316,7 @@ gdk_window_warp_pointer (GdkWindow      *window,
                     0, 0, 0, 0,        /* not source window -> move from anywhere */
                     x, y );
   }
+#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -293,8 +330,34 @@ extern bool g_isIdle;
 // local code (see below)
 //-----------------------------------------------------------------------------
 
-static void draw_frame( GtkWidget *widget, wxWindow *win )
+// returns the child of win which currently has focus or NULL if not found
+//
+// Note: can't be static, needed by textctrl.cpp.
+wxWindow *wxFindFocusedChild(wxWindowGTK *win)
 {
+    wxWindow *winFocus = wxWindowGTK::FindFocus();
+    if ( !winFocus )
+        return (wxWindow *)NULL;
+
+    if ( winFocus == win )
+        return (wxWindow *)win;
+
+    for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxWindow *child = wxFindFocusedChild(node->GetData());
+        if ( child )
+            return child;
+    }
+
+    return (wxWindow *)NULL;
+}
+
+static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
+{
+    // wxUniversal widgets draw the borders and scrollbars themselves
+#ifndef __WXUNIVERSAL__
     if (!win->m_hasVMT)
         return;
 
@@ -304,20 +367,20 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
     if (win->m_hasScrolling)
     {
             GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
-            
+
             GtkRequisition vscroll_req;
             vscroll_req.width = 2;
             vscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
                 (scroll_window->vscrollbar, &vscroll_req );
-                
+
             GtkRequisition hscroll_req;
             hscroll_req.width = 2;
             hscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
                 (scroll_window->hscrollbar, &hscroll_req );
 
-            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
+            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
 
             if (scroll_window->vscrollbar_visible)
             {
@@ -373,23 +436,27 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
         gdk_gc_unref( gc );
         return;
     }
+#endif // __WXUNIVERSAL__
 }
 
 //-----------------------------------------------------------------------------
 // "expose_event" of m_widget
 //-----------------------------------------------------------------------------
 
-static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
+gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win )
 {
-    if (gdk_event->count > 0) return;
+    if (gdk_event->count > 0) return FALSE;
+
     draw_frame( widget, win );
+
+    return TRUE;
 }
 
 //-----------------------------------------------------------------------------
 // "draw" of m_widget
 //-----------------------------------------------------------------------------
 
-static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindow *win )
+static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindowGTK *win )
 {
     draw_frame( widget, win );
 }
@@ -398,8 +465,9 @@ static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNU
 // key code mapping routines
 //-----------------------------------------------------------------------------
 
-static long map_to_unmodified_wx_keysym( KeySym keysym )
+static long map_to_unmodified_wx_keysym( GdkEventKey *event )
 {
+    KeySym keysym = event->keyval;
     guint key_code = 0;
 
     switch (keysym)
@@ -495,7 +563,11 @@ static long map_to_unmodified_wx_keysym( KeySym keysym )
         case GDK_F12:           key_code = WXK_F12;         break;
         default:
         {
-            if (keysym <= 0xFF)
+        if (event->length == 1)
+        {
+            key_code = toupper( (unsigned char)*event->string );
+        }
+        else if ((keysym & 0xFF) == keysym)
             {
                 guint upper = gdk_keyval_to_upper( (guint)keysym );
                 keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
@@ -507,8 +579,9 @@ static long map_to_unmodified_wx_keysym( KeySym keysym )
     return (key_code);
 }
 
-static long map_to_wx_keysym( KeySym keysym )
+static long map_to_wx_keysym( GdkEventKey *event )
 {
+    KeySym keysym = event->keyval;
     guint key_code = 0;
 
     switch (keysym)
@@ -594,7 +667,11 @@ static long map_to_wx_keysym( KeySym keysym )
         case GDK_F12:           key_code = WXK_F12;         break;
         default:
         {
-            if (keysym <= 0xFF)
+        if (event->length == 1)
+        {
+            key_code = (unsigned char)*event->string;
+        }
+        else if ((keysym & 0xFF) == keysym)
             {
                 key_code = (guint)keysym;
             }
@@ -604,90 +681,276 @@ static long map_to_wx_keysym( KeySym keysym )
     return (key_code);
 }
 
+//-----------------------------------------------------------------------------
+// "size_request" of m_widget
+//-----------------------------------------------------------------------------
+
+static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
+{
+    int w,h;
+    win->GetSize( &w, &h );
+    if (w < 2) w = 2;
+    if (h < 2) h = 2;
+
+    requisition->height = h;
+    requisition->width = w;
+}
+
 //-----------------------------------------------------------------------------
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
-static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
+static int gtk_window_expose_callback( GtkWidget *widget,
+                                       GdkEventExpose *gdk_event,
+                                       wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
-    if (!win->m_hasVMT)
-        return;
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+/*
+    if (win->GetName() == wxT("panel"))
+    {
+        wxPrintf( wxT("OnExpose from ") );
+        if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+            wxPrintf( win->GetClassInfo()->GetClassName() );
+        wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
+                                         (int)gdk_event->area.y,
+                                         (int)gdk_event->area.width,
+                                         (int)gdk_event->area.height );
+    }
+*/
+
+    GtkPizza *pizza = GTK_PIZZA (widget);
+
+    if (win->GetThemeEnabled())
+    {
+        wxWindow *parent = win->GetParent();
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+        if (!parent)
+            parent = win;
+
+        gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+            GTK_SHADOW_NONE, &gdk_event->area, parent->m_widget, "base", 0, 0, -1, -1);
+    }
 
     win->GetUpdateRegion().Union( gdk_event->area.x,
                                   gdk_event->area.y,
                                   gdk_event->area.width,
                                   gdk_event->area.height );
 
-/*
-    wxPrintf( "OnExpose from " );
-    if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-        wxPrintf( win->GetClassInfo()->GetClassName() );
-    wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
-                                (int)gdk_event->area.y,
-                                (int)gdk_event->area.width,
-                                (int)gdk_event->area.height );
-*/
+    if (gdk_event->count == 0)
+    {
+        win->m_clipPaintRegion = TRUE;
 
-    if (gdk_event->count > 0)
-        return;
+        wxWindowDC dc(win);
+        dc.SetClippingRegion(win->GetUpdateRegion());
+        wxEraseEvent eevent( win->GetId(), &dc );
+        eevent.SetEventObject( win );
+#if 1
+        (void)win->GetEventHandler()->ProcessEvent(eevent);
+#else // 0
+        if (!win->GetEventHandler()->ProcessEvent(eevent))
+        {
+            wxClientDC dc( win );
+            dc.SetBrush( wxBrush( win->GetBackgroundColour(), wxSOLID ) );
+            dc.SetPen( *wxTRANSPARENT_PEN );
 
-    wxEraseEvent eevent( win->GetId() );
-    eevent.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent(eevent);
+            wxRegionIterator upd( win->GetUpdateRegion() );
+            while (upd)
+            {
+                dc.DrawRectangle( upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
+                upd ++;
+            }
+        }
+#endif // 1/0
 
-    wxPaintEvent event( win->GetId() );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
+        wxNcPaintEvent eventNc( win->GetId() );
+        eventNc.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( eventNc );
 
-    win->GetUpdateRegion().Clear();
+        wxPaintEvent event( win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
+
+        win->GetUpdateRegion().Clear();
+
+        win->m_clipPaintRegion = FALSE;
+    }
+
+    /* The following code will result in all window-less widgets
+       being redrawn if the wxWindows class is given a chance to
+       paint *anything* because it will then be allowed to paint
+       over the window-less widgets */
+    GList *children = pizza->children;
+    while (children)
+    {
+        GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+        children = children->next;
+
+        GdkEventExpose child_event = *gdk_event;
+
+        if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+            GTK_WIDGET_DRAWABLE (child->widget) /* &&
+            gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
+        {
+            child_event.area.x = child->widget->allocation.x;
+            child_event.area.y = child->widget->allocation.y;
+            child_event.area.width = child->widget->allocation.width;
+            child_event.area.height = child->widget->allocation.height;
+            gtk_widget_event (child->widget, (GdkEvent*) &child_event);
+        }
+    }
+
+    return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// "event" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* GTK thinks it is clever and filters out a certain amount of "unneeded"
+   expose events. We need them, of course, so we override the main event
+   procedure in GtkWidget by giving our own handler for all system events.
+   There, we look for expose events ourselves whereas all other events are
+   handled normally. */
+
+gint gtk_window_event_event_callback( GtkWidget *widget,
+                                      GdkEventExpose *event,
+                                      wxWindow *win )
+{
+    if (event->type == GDK_EXPOSE)
+    {
+        gint ret = gtk_window_expose_callback( widget, event, win );
+        return ret;
+    }
+
+    return FALSE;
 }
 
 //-----------------------------------------------------------------------------
 // "draw" of m_wxwindow
 //-----------------------------------------------------------------------------
 
-static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget),
-                                      GdkRectangle *rect, wxWindow *win )
+/* This callback is a complete replacement of the gtk_pizza_draw() function,
+   which disabled. */
+
+static void gtk_window_draw_callback( GtkWidget *widget,
+                                      GdkRectangle *rect,
+                                      wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    if (!win->m_hasVMT)
+    if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
+        (win->GetChildren().GetCount() == 0))
+    {
         return;
-
-    win->GetUpdateRegion().Union( rect->x, rect->y,
-                                  rect->width, rect->height );
+    }
 
 /*
-    wxPrintf( "OnDraw from " );
-    if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-        printf( win->GetClassInfo()->GetClassName() );
-    wxPrintf( " %d %d %d %d\n", (int)rect->x,
-                                (int)rect->y,
-                                (int)rect->width,
-                                (int)rect->height );
+    if (win->GetName() == wxT("panel"))
+    {
+        wxPrintf( wxT("OnDraw from ") );
+        if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+            wxPrintf( win->GetClassInfo()->GetClassName() );
+        wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
+                                         (int)rect->y,
+                                         (int)rect->width,
+                                         (int)rect->height );
+    }
 */
 
-    wxEraseEvent eevent( win->GetId() );
+    GtkPizza *pizza = GTK_PIZZA (widget);
+
+    if (win->GetThemeEnabled())
+    {
+        wxWindow *parent = win->GetParent();
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+        if (!parent)
+            parent = win;
+
+        gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+            GTK_SHADOW_NONE, rect, parent->m_widget, "base", 0, 0, -1, -1);
+    }
+
+
+    if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
+         (pizza->clear_on_draw))
+    {
+        gdk_window_clear_area( pizza->bin_window,
+                               rect->x, rect->y, rect->width, rect->height);
+    }
+
+    win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
+
+    win->m_clipPaintRegion = TRUE;
+
+    wxWindowDC dc(win);
+    dc.SetClippingRegion(win->GetUpdateRegion());
+    wxEraseEvent eevent( win->GetId(), &dc );
     eevent.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent(eevent);
+
+#if 1
+    (void)win->GetEventHandler()->ProcessEvent(eevent);
+#else
+    if (!win->GetEventHandler()->ProcessEvent(eevent))
+    {
+        if (!win->GetEventHandler()->ProcessEvent(eevent))
+        {
+            wxClientDC dc( win );
+            dc.SetBrush( wxBrush( win->GetBackgroundColour(), wxSOLID ) );
+            dc.SetPen( *wxTRANSPARENT_PEN );
+
+            wxRegionIterator upd( win->GetUpdateRegion() );
+            while (upd)
+            {
+                dc.DrawRectangle( upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
+                upd ++;
+            }
+        }
+    }
+#endif
+
+    wxNcPaintEvent eventNc( win->GetId() );
+    eventNc.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( eventNc );
 
     wxPaintEvent event( win->GetId() );
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
 
     win->GetUpdateRegion().Clear();
+
+    win->m_clipPaintRegion = FALSE;
+
+
+    GList *children = pizza->children;
+    while (children)
+    {
+            GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+            children = children->next;
+
+            GdkRectangle child_area;
+            if (gtk_widget_intersect (child->widget, rect, &child_area))
+            {
+                gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
+            }
+    }
 }
 
 //-----------------------------------------------------------------------------
 // "key_press_event" from any window
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
+static gint gtk_window_key_press_callback( GtkWidget *widget,
+                                           GdkEventKey *gdk_event,
+                                           wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -697,13 +960,14 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
     if (!win->m_hasVMT) return FALSE;
     if (g_blockEventsOnDrag) return FALSE;
 
+
 /*
     wxString tmp;
     tmp += (char)gdk_event->keyval;
     printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
     printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
 */
-    
+
     int x = 0;
     int y = 0;
     GdkModifierType state;
@@ -711,7 +975,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
 
     bool ret = FALSE;
 
-    long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+    long key_code = map_to_unmodified_wx_keysym( gdk_event );
     /* sending unknown key events doesn't really make sense */
     if (key_code == 0) return FALSE;
 
@@ -731,7 +995,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
 #if wxUSE_ACCEL
     if (!ret)
     {
-        wxWindow *ancestor = win;
+        wxWindowGTK *ancestor = win;
         while (ancestor)
         {
             int command = ancestor->GetAcceleratorTable()->GetCommand( event );
@@ -741,7 +1005,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
                 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
                 break;
             }
-            if (ancestor->m_isFrame)
+            if (ancestor->IsTopLevel())
                 break;
             ancestor = ancestor->GetParent();
         }
@@ -751,7 +1015,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
     /* wxMSW doesn't send char events with Alt pressed */
     /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
        will only be sent if it is not in an accelerator table. */
-    key_code = map_to_wx_keysym( gdk_event->keyval );
+    key_code = map_to_wx_keysym( gdk_event );
 
     if ( (!ret) &&
          (key_code != 0))
@@ -773,7 +1037,12 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
     /* win is a control: tab can be propagated up */
     if ( (!ret) &&
          ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
+// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
+//     have this style, yet choose not to process this particular TAB in which
+//     case TAB must still work as a navigational character
+#if 0
          (!win->HasFlag(wxTE_PROCESS_TAB)) &&
+#endif // 0
          (win->GetParent()) &&
          (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
     {
@@ -803,7 +1072,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
     if ( (!ret) &&
          (gdk_event->keyval == GDK_F10) )
     {
-        wxWindow *ancestor = win;
+        wxWindowGTK *ancestor = win;
         while (ancestor)
         {
             if (wxIsKindOf(ancestor,wxFrame))
@@ -841,7 +1110,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
 // "key_release_event" from any window
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
+static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -864,7 +1133,7 @@ static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk
     printf( "\n" );
 */
 
-    long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+    long key_code = map_to_unmodified_wx_keysym( gdk_event );
 
     /* sending unknown key events doesn't really make sense */
     if (key_code == 0) return FALSE;
@@ -895,11 +1164,47 @@ static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk
     return FALSE;
 }
 
+// ----------------------------------------------------------------------------
+// mouse event processing helper
+// ----------------------------------------------------------------------------
+
+static void AdjustEventButtonState(wxMouseEvent& event)
+{
+    // GDK reports the old state of the button for a button press event, but
+    // for compatibility with MSW and common sense we want m_leftDown be TRUE
+    // for a LEFT_DOWN event, not FALSE, so we will invert
+    // left/right/middleDown for the corresponding click events
+
+    if ((event.GetEventType() == wxEVT_LEFT_DOWN) ||
+        (event.GetEventType() == wxEVT_LEFT_DCLICK) ||
+        (event.GetEventType() == wxEVT_LEFT_UP))
+    {
+        event.m_leftDown = !event.m_leftDown;
+        return;
+    }
+
+    if ((event.GetEventType() == wxEVT_MIDDLE_DOWN) ||
+        (event.GetEventType() == wxEVT_MIDDLE_DCLICK) ||
+        (event.GetEventType() == wxEVT_MIDDLE_UP))
+    {
+        event.m_middleDown = !event.m_middleDown;
+        return;
+    }
+
+    if ((event.GetEventType() == wxEVT_RIGHT_DOWN) ||
+        (event.GetEventType() == wxEVT_RIGHT_DCLICK) ||
+        (event.GetEventType() == wxEVT_RIGHT_UP))
+    {
+        event.m_rightDown = !event.m_rightDown;
+        return;
+    }
+}
+
 //-----------------------------------------------------------------------------
 // "button_press_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
+static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -934,7 +1239,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
         }
     }
 
-    wxEventType event_type = wxEVT_LEFT_DOWN;
+    wxEventType event_type = wxEVT_NULL;
 
     if (gdk_event->button == 1)
     {
@@ -964,6 +1269,12 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
         }
     }
 
+    if ( event_type == wxEVT_NULL )
+    {
+        // unknown mouse button or click type
+        return FALSE;
+    }
+
     wxMouseEvent event( event_type );
     event.SetTimestamp( gdk_event->time );
     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
@@ -977,6 +1288,8 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
     event.m_x = (wxCoord)gdk_event->x;
     event.m_y = (wxCoord)gdk_event->y;
 
+    AdjustEventButtonState(event);
+
     // Some control don't have their own X window and thus cannot get
     // any events.
 
@@ -994,7 +1307,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
         wxNode *node = win->GetChildren().First();
         while (node)
         {
-            wxWindow *child = (wxWindow*)node->Data();
+            wxWindowGTK *child = (wxWindowGTK*)node->Data();
 
             node = node->Next();
             if (!child->IsShown())
@@ -1065,7 +1378,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
 // "button_release_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
+static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1092,6 +1405,7 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
         case 1: event_type = wxEVT_LEFT_UP; break;
         case 2: event_type = wxEVT_MIDDLE_UP; break;
         case 3: event_type = wxEVT_RIGHT_UP; break;
+        default: return FALSE;
     }
 
     wxMouseEvent event( event_type );
@@ -1106,6 +1420,8 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
     event.m_x = (wxCoord)gdk_event->x;
     event.m_y = (wxCoord)gdk_event->y;
 
+    AdjustEventButtonState(event);
+
     // Some control don't have their own X window and thus cannot get
     // any events.
 
@@ -1123,7 +1439,7 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
         wxNode *node = win->GetChildren().First();
         while (node)
         {
-            wxWindow *child = (wxWindow*)node->Data();
+            wxWindowGTK *child = (wxWindowGTK*)node->Data();
 
             node = node->Next();
             if (!child->IsShown())
@@ -1181,11 +1497,31 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
     return FALSE;
 }
 
+// ============================================================================
+// the mouse events
+// ============================================================================
+
+// init wxMouseEvent with the info from gdk_event
+#define InitMouseEvent(event, gdk_event) \
+    event.SetTimestamp( gdk_event->time ); \
+    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
+    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
+    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
+    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
+    event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
+    event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
+    event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
+\
+    event.m_x = (wxCoord)gdk_event->x; \
+    event.m_y = (wxCoord)gdk_event->y \
+
 //-----------------------------------------------------------------------------
 // "motion_notify_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
+static gint gtk_window_motion_notify_callback( GtkWidget *widget,
+                                               GdkEventMotion *gdk_event,
+                                               wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1216,23 +1552,30 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
 */
 
     wxMouseEvent event( wxEVT_MOTION );
-    event.SetTimestamp( gdk_event->time );
-    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
-    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
-    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
-    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
-    event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
-    event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
-    event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
+    InitMouseEvent(event, gdk_event);
 
-    event.m_x = (wxCoord)gdk_event->x;
-    event.m_y = (wxCoord)gdk_event->y;
-
-    // Some control don't have their own X window and thus cannot get
-    // any events.
-
-    if (!g_captureWindow)
+    if ( g_captureWindow )
+    {
+        // synthetize a mouse enter or leave event if needed
+        GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL);
+        bool hasMouse = winUnderMouse == gdk_event->window;
+        if ( hasMouse != g_captureWindowHasMouse )
+        {
+            // the mouse changed window
+            g_captureWindowHasMouse = hasMouse;
+
+            wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW
+                                                       : wxEVT_LEAVE_WINDOW);
+            InitMouseEvent(event, gdk_event);
+            event.SetEventObject(win);
+            win->GetEventHandler()->ProcessEvent(event);
+        }
+    }
+    else // no capture
     {
+        // Some control don't have their own X window and thus cannot get
+        // any events.
+
         wxCoord x = event.m_x;
         wxCoord y = event.m_y;
         if (win->m_wxwindow)
@@ -1245,7 +1588,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
         wxNode *node = win->GetChildren().First();
         while (node)
         {
-            wxWindow *child = (wxWindow*)node->Data();
+            wxWindowGTK *child = (wxWindowGTK*)node->Data();
 
             node = node->Next();
             if (!child->IsShown())
@@ -1307,7 +1650,9 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
 // "focus_in_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
+static gint gtk_window_focus_in_callback( GtkWidget *widget,
+                                          GdkEvent *WXUNUSED(event),
+                                          wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1331,6 +1676,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(
             break;
     }
 
+    g_focusWindowLast =
     g_focusWindow = win;
 
 /*
@@ -1353,15 +1699,34 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(
         gdk_im_begin(win->m_ic, win->m_wxwindow->window);
 #endif
 
+#if wxUSE_CARET
+    // caret needs to be informed about focus change
+    wxCaret *caret = win->GetCaret();
+    if ( caret )
+    {
+        caret->OnSetFocus();
+    }
+#endif // wxUSE_CARET
+
+    if (win->IsTopLevel())
+    {
+        wxActivateEvent event( wxEVT_ACTIVATE, TRUE, win->GetId() );
+        event.SetEventObject( win );
+
+        // ignore return value
+        win->GetEventHandler()->ProcessEvent( event );
+    }
+
     wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
     event.SetEventObject( win );
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
-        return TRUE;
+       gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
+       return TRUE;
     }
 
+
     return FALSE;
 }
 
@@ -1369,7 +1734,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(
 // "focus_out_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
+static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1384,7 +1749,11 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
     // g_sendActivateEvent to -1
     g_sendActivateEvent = 0;
 
-    g_focusWindow = (wxWindow *)NULL;
+    wxWindowGTK *winFocus = wxFindFocusedChild(win);
+    if ( winFocus )
+        win = winFocus;
+
+    g_focusWindow = (wxWindowGTK *)NULL;
 
 /*
     printf( "OnKillFocus from " );
@@ -1398,6 +1767,24 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
         gdk_im_end();
 #endif
 
+#if wxUSE_CARET
+    // caret needs to be informed about focus change
+    wxCaret *caret = win->GetCaret();
+    if ( caret )
+    {
+        caret->OnKillFocus();
+    }
+#endif // wxUSE_CARET
+
+    if (win->IsTopLevel())
+    {
+        wxActivateEvent event( wxEVT_ACTIVATE, FALSE, win->GetId() );
+        event.SetEventObject( win );
+
+        // ignore return value
+        win->GetEventHandler()->ProcessEvent( event );
+    }
+
     wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
     event.SetEventObject( win );
 
@@ -1414,7 +1801,7 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
 // "enter_notify_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
+static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1438,13 +1825,7 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     gdk_window_get_pointer( widget->window, &x, &y, &state );
 
-    event.m_shiftDown = (state & GDK_SHIFT_MASK);
-    event.m_controlDown = (state & GDK_CONTROL_MASK);
-    event.m_altDown = (state & GDK_MOD1_MASK);
-    event.m_metaDown = (state & GDK_MOD2_MASK);
-    event.m_leftDown = (state & GDK_BUTTON1_MASK);
-    event.m_middleDown = (state & GDK_BUTTON2_MASK);
-    event.m_rightDown = (state & GDK_BUTTON3_MASK);
+    InitMouseEvent(event, gdk_event);
 
     event.m_x = x;
     event.m_y = y;
@@ -1462,7 +1843,7 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 // "leave_notify_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
+static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1510,7 +1891,7 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 // "value_changed" from m_vAdjust
 //-----------------------------------------------------------------------------
 
-static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
+static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1546,7 +1927,7 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
 // "value_changed" from m_hAdjust
 //-----------------------------------------------------------------------------
 
-static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
+static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1577,70 +1958,22 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
     win->GetEventHandler()->ProcessEvent( event );
 }
 
-//-----------------------------------------------------------------------------
-// "changed" from m_vAdjust
-//-----------------------------------------------------------------------------
-
-static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
-{
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (g_blockEventsOnDrag) return;
-    if (!win->m_hasVMT) return;
-
-    wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
-    int value = (int)(win->m_vAdjust->value+0.5);
-
-    wxScrollWinEvent event( command, value, wxVERTICAL );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
-}
-
-//-----------------------------------------------------------------------------
-// "changed" from m_hAdjust
-//-----------------------------------------------------------------------------
-
-static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
-{
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (g_blockEventsOnDrag) return;
-    if (!win->m_hasVMT) return;
-
-    wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
-    int value = (int)(win->m_hAdjust->value+0.5);
-
-    wxScrollWinEvent event( command, value, wxHORIZONTAL );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
-}
-
 //-----------------------------------------------------------------------------
 // "button_press_event" from scrollbar
 //-----------------------------------------------------------------------------
 
-static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
-                                                 GdkEventButton *WXUNUSED(gdk_event),
-                                                 wxWindow *win)
+static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
+                                                 GdkEventButton *gdk_event,
+                                                 wxWindowGTK *win)
 {
     DEBUG_MAIN_THREAD
 
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-//  don't test here as we can release the mouse while being over
-//  a different window than the slider
-//
-//    if (gdk_event->window != widget->slider) return FALSE;
 
     g_blockEventsOnScroll = TRUE;
-    win->m_isScrolling = TRUE;
+    win->m_isScrolling = (gdk_event->window == widget->slider);
 
     return FALSE;
 }
@@ -1651,41 +1984,41 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
 
 static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
                                                    GdkEventButton *WXUNUSED(gdk_event),
-                                                   wxWindow *win)
+                                                   wxWindowGTK *win)
 {
     DEBUG_MAIN_THREAD
 
-
 //  don't test here as we can release the mouse while being over
 //  a different window than the slider
 //
 //    if (gdk_event->window != widget->slider) return FALSE;
 
-    wxASSERT( win->m_isScrolling );
-
     g_blockEventsOnScroll = FALSE;
-    win->m_isScrolling = FALSE;
 
-    wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
-    int value = -1;
-    int dir = -1;
-    
-    GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
-    if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
+    if (win->m_isScrolling)
     {
-        value = (int)(win->m_hAdjust->value+0.5);
-        dir = wxHORIZONTAL;
-    }
-    if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
-    {
-        value = (int)(win->m_vAdjust->value+0.5);
-        dir = wxVERTICAL;
+        wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
+        int value = -1;
+        int dir = -1;
+
+        GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
+        if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
+        {
+            value = (int)(win->m_hAdjust->value+0.5);
+            dir = wxHORIZONTAL;
+        }
+        if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
+        {
+            value = (int)(win->m_vAdjust->value+0.5);
+            dir = wxVERTICAL;
+        }
+
+        wxScrollWinEvent event( command, value, dir );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
     }
 
-    wxScrollWinEvent event( command, value, dir );
-    event.SetScrolling( FALSE );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
+    win->m_isScrolling = FALSE;
 
     return FALSE;
 }
@@ -1697,7 +2030,8 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
 
 wxWindow *wxWindowBase::FindFocus()
 {
-    return g_focusWindow;
+    // the cast is necessary when we compile in wxUniversal mode
+    return (wxWindow *)g_focusWindow;
 }
 
 //-----------------------------------------------------------------------------
@@ -1739,18 +2073,18 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
 {
     if (g_isIdle)
         wxapp_install_idle_handler();
-    
+
     if (!win->m_hasScrolling) return;
-    
+
     int client_width = 0;
     int client_height = 0;
     win->GetClientSize( &client_width, &client_height );
     if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
         return;
-        
+
     win->m_oldClientWidth = client_width;
     win->m_oldClientHeight = client_height;
-    
+
     if (!win->m_nativeSizeEvent)
     {
         wxSizeEvent event( win->GetSize(), win->GetId() );
@@ -1771,11 +2105,11 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
 static
 void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
                                  GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
-                                 wxWindow* WXUNUSED_UNLESS_XIM(win) )
+                                 wxWindowGTK* WXUNUSED_UNLESS_XIM(win) )
 {
     if (g_isIdle)
         wxapp_install_idle_handler();
-        
+
 #ifdef HAVE_XIM
     if (!win->m_ic)
         return;
@@ -1800,7 +2134,7 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
 
 static gint
 gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
-                                wxWindow * WXUNUSED_UNLESS_XIM(win) )
+                                wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
 {
     if (g_isIdle)
         wxapp_install_idle_handler();
@@ -1812,7 +2146,7 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
 
     win->m_icattr = gdk_ic_attr_new();
     if (!win->m_icattr) return FALSE;
-    
+
     gint width, height;
     GdkEventMask mask;
     GdkColormap *colormap;
@@ -1821,24 +2155,24 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
     GdkIMStyle style;
     GdkIMStyle supported_style = (GdkIMStyle)
                                   (GDK_IM_PREEDIT_NONE |
-                                  GDK_IM_PREEDIT_NOTHING |
-                                  GDK_IM_PREEDIT_POSITION |
-                                  GDK_IM_STATUS_NONE |
-                                  GDK_IM_STATUS_NOTHING);
+                                   GDK_IM_PREEDIT_NOTHING |
+                                   GDK_IM_PREEDIT_POSITION |
+                                   GDK_IM_STATUS_NONE |
+                                   GDK_IM_STATUS_NOTHING);
 
     if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
-       supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
+        supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
 
     attr->style = style = gdk_im_decide_style (supported_style);
     attr->client_window = widget->window;
 
     if ((colormap = gtk_widget_get_colormap (widget)) !=
-           gtk_widget_get_default_colormap ())
+            gtk_widget_get_default_colormap ())
     {
-       attrmask |= GDK_IC_PREEDIT_COLORMAP;
-       attr->preedit_colormap = colormap;
+        attrmask |= GDK_IC_PREEDIT_COLORMAP;
+        attr->preedit_colormap = colormap;
     }
-    
+
     attrmask |= GDK_IC_PREEDIT_FOREGROUND;
     attrmask |= GDK_IC_PREEDIT_BACKGROUND;
     attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
@@ -1846,57 +2180,57 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
 
     switch (style & GDK_IM_PREEDIT_MASK)
     {
-       case GDK_IM_PREEDIT_POSITION:
-         if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
-           {
-             g_warning ("over-the-spot style requires fontset");
-             break;
-           }
+        case GDK_IM_PREEDIT_POSITION:
+            if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+            {
+                g_warning ("over-the-spot style requires fontset");
+                break;
+            }
 
-         gdk_window_get_size (widget->window, &width, &height);
+            gdk_window_get_size (widget->window, &width, &height);
 
-         attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
-         attr->spot_location.x = 0;
-         attr->spot_location.y = height;
-         attr->preedit_area.x = 0;
-         attr->preedit_area.y = 0;
-         attr->preedit_area.width = width;
-         attr->preedit_area.height = height;
-         attr->preedit_fontset = widget->style->font;
+            attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
+            attr->spot_location.x = 0;
+            attr->spot_location.y = height;
+            attr->preedit_area.x = 0;
+            attr->preedit_area.y = 0;
+            attr->preedit_area.width = width;
+            attr->preedit_area.height = height;
+            attr->preedit_fontset = widget->style->font;
 
-         break;
+            break;
     }
-       
+
       win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
-     
+
       if (win->m_ic == NULL)
-       g_warning ("Can't create input context.");
+          g_warning ("Can't create input context.");
       else
-       {
-         mask = gdk_window_get_events (widget->window);
-         mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
-         gdk_window_set_events (widget->window, mask);
-
-         if (GTK_WIDGET_HAS_FOCUS(widget))
-           gdk_im_begin (win->m_ic, widget->window);
-       }
-#endif
+      {
+          mask = gdk_window_get_events (widget->window);
+          mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
+          gdk_window_set_events (widget->window, mask);
+
+          if (GTK_WIDGET_HAS_FOCUS(widget))
+              gdk_im_begin (win->m_ic, widget->window);
+      }
+#endif // HAVE_XIM
 
     return FALSE;
 }
 
 //-----------------------------------------------------------------------------
-// InsertChild for wxWindow.
+// InsertChild for wxWindowGTK.
 //-----------------------------------------------------------------------------
 
-/* Callback for wxWindow. This very strange beast has to be used because
+/* Callback for wxWindowGTK. This very strange beast has to be used because
  * C++ has no virtual methods in a constructor. We have to emulate a
  * virtual function here as wxNotebook requires a different way to insert
  * a child in it. I had opted for creating a wxNotebookPage window class
  * which would have made this superfluous (such in the MDI window system),
  * but no-one was listening to me... */
 
-static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
+static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
 {
     /* the window might have been scrolled already, do we
        have to adapt the position */
@@ -1916,18 +2250,25 @@ static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
 // global functions
 //-----------------------------------------------------------------------------
 
-wxWindowwxGetActiveWindow()
+wxWindow *wxGetActiveWindow()
 {
-    return g_focusWindow;
+    // the cast is necessary when we compile in wxUniversal mode
+    return (wxWindow *)g_focusWindow;
 }
 
 //-----------------------------------------------------------------------------
-// wxWindow
+// wxWindowGTK
 //-----------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
+// method
+#ifdef __WXUNIVERSAL__
+    IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK, wxWindowBase)
+#else // __WXGTK__
+    IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+#endif // __WXUNIVERSAL__/__WXGTK__
 
-void wxWindow::Init()
+void wxWindowGTK::Init()
 {
     // common init
     InitBase();
@@ -1968,36 +2309,47 @@ void wxWindow::Init()
     m_isFrame = FALSE;
     m_acceptsFocus = FALSE;
 
+    m_clipPaintRegion = FALSE;
+
     m_cursor = *wxSTANDARD_CURSOR;
-    
+
+    m_delayedForegroundColour = FALSE;
+    m_delayedBackgroundColour = FALSE;
+
 #ifdef HAVE_XIM
     m_ic = (GdkIC*) NULL;
     m_icattr = (GdkICAttr*) NULL;
 #endif
 }
 
-wxWindow::wxWindow()
+wxWindowGTK::wxWindowGTK()
 {
     Init();
 }
 
-wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
-                    const wxPoint &pos, const wxSize &size,
-                    long style, const wxString &name  )
+wxWindowGTK::wxWindowGTK( wxWindow *parent,
+                          wxWindowID id,
+                          const wxPoint &pos,
+                          const wxSize &size,
+                          long style,
+                          const wxString &name  )
 {
     Init();
 
     Create( parent, id, pos, size, style, name );
 }
 
-bool wxWindow::Create( wxWindow *parent, wxWindowID id,
-                       const wxPoint &pos, const wxSize &size,
-                       long style, const wxString &name  )
+bool wxWindowGTK::Create( wxWindow *parent,
+                          wxWindowID id,
+                          const wxPoint &pos,
+                          const wxSize &size,
+                          long style,
+                          const wxString &name  )
 {
     if (!PreCreation( parent, pos, size ) ||
         !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
     {
-        wxFAIL_MSG( wxT("wxWindow creation failed") );
+        wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
         return FALSE;
     }
 
@@ -2006,18 +2358,9 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
     m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
     GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
 
-#ifdef __WXDEBUG__
-    debug_focus_in( m_widget, wxT("wxWindow::m_widget"), name );
-#endif
-
     GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
 
-#ifdef __WXDEBUG__
-    debug_focus_in( scrolledWindow->hscrollbar, wxT("wxWindow::hsrcollbar"), name );
-    debug_focus_in( scrolledWindow->vscrollbar, wxT("wxWindow::vsrcollbar"), name );
-#endif
-
-    GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+    GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
     scroll_class->scrollbar_spacing = 0;
 
     gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
@@ -2027,12 +2370,9 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
 
     m_wxwindow = gtk_pizza_new();
 
-#ifdef __WXDEBUG__
-    debug_focus_in( m_wxwindow, wxT("wxWindow::m_wxwindow"), name );
-#endif
-
     gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
 
+#ifndef __WXUNIVERSAL__
 #if (GTK_MINOR_VERSION > 0)
     GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
 
@@ -2068,6 +2408,7 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
         gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
     }
 #endif // GTK_MINOR_VERSION
+#endif // __WXUNIVERSAL__
 
     GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
     m_acceptsFocus = TRUE;
@@ -2119,11 +2460,6 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
     gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
           (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
 
-    gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
-          (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
-    gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
-          (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
-
     gtk_widget_show( m_wxwindow );
 
     if (m_parent)
@@ -2136,8 +2472,11 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
     return TRUE;
 }
 
-wxWindow::~wxWindow()
+wxWindowGTK::~wxWindowGTK()
 {
+    if (g_focusWindow == this)
+        g_focusWindow = NULL;
+
     m_isBeingDeleted = TRUE;
     m_hasVMT = FALSE;
 
@@ -2158,7 +2497,11 @@ wxWindow::~wxWindow()
 
     if (m_widgetStyle)
     {
-        gtk_style_unref( m_widgetStyle );
+#if DISABLE_STYLE_IF_BROKEN_THEME
+        // don't delete if it's a pixmap theme style
+        if (!m_widgetStyle->engine_data)
+            gtk_style_unref( m_widgetStyle );
+#endif
         m_widgetStyle = (GtkStyle*) NULL;
     }
 
@@ -2175,7 +2518,7 @@ wxWindow::~wxWindow()
     }
 }
 
-bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos,  const wxSize &size )
+bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const wxSize &size )
 {
     wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
 
@@ -2207,7 +2550,7 @@ bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos,  const wxSize
     return TRUE;
 }
 
-void wxWindow::PostCreation()
+void wxWindowGTK::PostCreation()
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
 
@@ -2216,11 +2559,20 @@ void wxWindow::PostCreation()
         if (!m_noExpose)
         {
             /* these get reported to wxWindows -> wxPaintEvent */
+
+            gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
+
             gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
                 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
 
             gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
                 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
+
+            if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
+            {
+                gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
+                    GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
+            }
         }
 
 #if (GTK_MINOR_VERSION > 0)
@@ -2244,8 +2596,8 @@ void wxWindow::PostCreation()
     else
     {
         // For dialogs and frames, we are interested mainly in
-       // m_widget's focus.
-       
+        // m_widget's focus.
+
         gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
             GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
 
@@ -2261,26 +2613,37 @@ void wxWindow::PostCreation()
        been realized, so we do this directly after realization */
     gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
                             GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
+
     if (m_wxwindow)
     {
-        /* Catch native resize events. */
+        // Catch native resize events
         gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
                             GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
-                            
-        /* Initialize XIM support. */
+
+        // Initialize XIM support
         gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
 
-        /* And resize XIM window. */
+        // And resize XIM window
         gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
     }
-    
+
+    if (!GTK_IS_COMBO(m_widget))
+    {
+        // This is needed if we want to add our windows into native
+        // GTK control, such as the toolbar. With this callback, the
+        // toolbar gets to know the correct size (the one set by the
+        // programmer). Sadly, it misbehaves for wxComboBox. FIXME
+        // when moving to GTK 2.0.
+        gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
+                            GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
+    }
+
     m_hasVMT = TRUE;
 }
 
-void wxWindow::ConnectWidget( GtkWidget *widget )
+void wxWindowGTK::ConnectWidget( GtkWidget *widget )
 {
     gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
       GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
@@ -2304,7 +2667,7 @@ void wxWindow::ConnectWidget( GtkWidget *widget )
       GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
 }
 
-bool wxWindow::Destroy()
+bool wxWindowGTK::Destroy()
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
 
@@ -2313,15 +2676,19 @@ bool wxWindow::Destroy()
     return wxWindowBase::Destroy();
 }
 
-void wxWindow::DoMoveWindow(int x, int y, int width, int height)
+void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
 {
     gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
 }
-    
-void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
+
+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("wxWindow::SetSize requires parent.\n") );
+    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;
@@ -2386,6 +2753,12 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
 
     if (m_hasScrolling)
     {
+        /* Sometimes the client area changes size without the
+           whole windows's size changing, but if the whole
+           windows's size doesn't change, no wxSizeEvent will
+           normally be sent. Here we add an extra test if
+           the client test has been changed and this will
+           be used then. */
         GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
     }
 
@@ -2406,7 +2779,7 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
     m_resizing = FALSE;
 }
 
-void wxWindow::OnInternalIdle()
+void wxWindowGTK::OnInternalIdle()
 {
     if ( g_sendActivateEvent != -1 )
     {
@@ -2415,7 +2788,9 @@ void wxWindow::OnInternalIdle()
         // do it only once
         g_sendActivateEvent = -1;
 
-        wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
+        wxTheApp->SetActive(activate, (wxWindow *)g_focusWindowLast);
+
+        wxActivateEvent event(wxEVT_ACTIVATE_APP, activate, GetId());
         event.SetEventObject(this);
 
         (void)GetEventHandler()->ProcessEvent(event);
@@ -2458,7 +2833,7 @@ void wxWindow::OnInternalIdle()
     UpdateWindowUI();
 }
 
-void wxWindow::DoGetSize( int *width, int *height ) const
+void wxWindowGTK::DoGetSize( int *width, int *height ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2466,7 +2841,7 @@ void wxWindow::DoGetSize( int *width, int *height ) const
     if (height) (*height) = m_height;
 }
 
-void wxWindow::DoSetClientSize( int width, int height )
+void wxWindowGTK::DoSetClientSize( int width, int height )
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2479,6 +2854,7 @@ void wxWindow::DoSetClientSize( int width, int height )
         int dw = 0;
         int dh = 0;
 
+#ifndef __WXUNIVERSAL__
         if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
         {
             /* when using GTK 1.2 we set the shadow border size to 2 */
@@ -2491,24 +2867,25 @@ void wxWindow::DoSetClientSize( int width, int height )
             dw += 1 * 2;
             dh += 1 * 2;
         }
+#endif // __WXUNIVERSAL__
 
         if (m_hasScrolling)
         {
             GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-            
+
             GtkRequisition vscroll_req;
             vscroll_req.width = 2;
             vscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
                 (scroll_window->vscrollbar, &vscroll_req );
-                
+
             GtkRequisition hscroll_req;
             hscroll_req.width = 2;
             hscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
                 (scroll_window->hscrollbar, &hscroll_req );
 
-            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
 
             if (scroll_window->vscrollbar_visible)
             {
@@ -2527,7 +2904,7 @@ void wxWindow::DoSetClientSize( int width, int height )
     }
 }
 
-void wxWindow::DoGetClientSize( int *width, int *height ) const
+void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2541,6 +2918,7 @@ void wxWindow::DoGetClientSize( int *width, int *height ) const
         int dw = 0;
         int dh = 0;
 
+#ifndef __WXUNIVERSAL__
         if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
         {
             /* when using GTK 1.2 we set the shadow border size to 2 */
@@ -2553,24 +2931,25 @@ void wxWindow::DoGetClientSize( int *width, int *height ) const
             dw += 1 * 2;
             dh += 1 * 2;
         }
+#endif // __WXUNIVERSAL__
 
         if (m_hasScrolling)
         {
             GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-            
+
             GtkRequisition vscroll_req;
             vscroll_req.width = 2;
             vscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
                 (scroll_window->vscrollbar, &vscroll_req );
-                
+
             GtkRequisition hscroll_req;
             hscroll_req.width = 2;
             hscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
                 (scroll_window->hscrollbar, &hscroll_req );
 
-            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
 
             if (scroll_window->vscrollbar_visible)
             {
@@ -2588,9 +2967,16 @@ void wxWindow::DoGetClientSize( int *width, int *height ) const
         if (width) (*width) = m_width - dw;
         if (height) (*height) = m_height - dh;
     }
+
+/*
+    printf( "GetClientSize, name %s ", GetName().c_str() );
+    if (width) printf( " width = %d", (*width) );
+    if (height) printf( " height = %d", (*height) );
+    printf( "\n" );
+*/
 }
 
-void wxWindow::DoGetPosition( int *x, int *y ) const
+void wxWindowGTK::DoGetPosition( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2607,7 +2993,7 @@ void wxWindow::DoGetPosition( int *x, int *y ) const
     if (y) (*y) = m_y - dy;
 }
 
-void wxWindow::DoClientToScreen( int *x, int *y ) const
+void wxWindowGTK::DoClientToScreen( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2636,7 +3022,7 @@ void wxWindow::DoClientToScreen( int *x, int *y ) const
     if (y) *y += org_y;
 }
 
-void wxWindow::DoScreenToClient( int *x, int *y ) const
+void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2665,7 +3051,7 @@ void wxWindow::DoScreenToClient( int *x, int *y ) const
     if (y) *y -= org_y;
 }
 
-bool wxWindow::Show( bool show )
+bool wxWindowGTK::Show( bool show )
 {
     wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
 
@@ -2683,7 +3069,24 @@ bool wxWindow::Show( bool show )
     return TRUE;
 }
 
-bool wxWindow::Enable( bool enable )
+static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
+{
+    win->OnParentEnable(enable);
+
+    // Recurse, so that children have the opportunity to Do The Right Thing
+    // and reset colours that have been messed up by a parent's (really ancestor's)
+    // Enable call
+    for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxWindow *child = node->GetData();
+        if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
+            wxWindowNotifyEnable(child, enable);
+    }
+}
+
+bool wxWindowGTK::Enable( bool enable )
 {
     wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
 
@@ -2697,10 +3100,12 @@ bool wxWindow::Enable( bool enable )
     if ( m_wxwindow )
         gtk_widget_set_sensitive( m_wxwindow, enable );
 
+    wxWindowNotifyEnable(this, enable);
+
     return TRUE;
 }
 
-int wxWindow::GetCharHeight() const
+int wxWindowGTK::GetCharHeight() const
 {
     wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
 
@@ -2711,7 +3116,7 @@ int wxWindow::GetCharHeight() const
     return font->ascent + font->descent;
 }
 
-int wxWindow::GetCharWidth() const
+int wxWindowGTK::GetCharWidth() const
 {
     wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
 
@@ -2722,7 +3127,7 @@ int wxWindow::GetCharWidth() const
     return gdk_string_width( font, "H" );
 }
 
-void wxWindow::GetTextExtent( const wxString& string,
+void wxWindowGTK::GetTextExtent( const wxString& string,
                               int *x,
                               int *y,
                               int *descent,
@@ -2741,10 +3146,10 @@ void wxWindow::GetTextExtent( const wxString& string,
     if (externalLeading) (*externalLeading) = 0;  // ??
 }
 
-void wxWindow::SetFocus()
+void wxWindowGTK::SetFocus()
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-    
+
     if (m_wxwindow)
     {
         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
@@ -2769,17 +3174,17 @@ void wxWindow::SetFocus()
     }
 }
 
-bool wxWindow::AcceptsFocus() const
+bool wxWindowGTK::AcceptsFocus() const
 {
     return m_acceptsFocus && wxWindowBase::AcceptsFocus();
 }
 
-bool wxWindow::Reparent( wxWindowBase *newParentBase )
+bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
 {
     wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
 
-    wxWindow *oldParent = m_parent,
-             *newParent = (wxWindow *)newParentBase;
+    wxWindowGTK *oldParent = m_parent,
+             *newParent = (wxWindowGTK *)newParentBase;
 
     wxASSERT( GTK_IS_WIDGET(m_widget) );
 
@@ -2810,7 +3215,7 @@ bool wxWindow::Reparent( wxWindowBase *newParentBase )
     return TRUE;
 }
 
-void wxWindow::DoAddChild(wxWindow *child)
+void wxWindowGTK::DoAddChild(wxWindowGTK *child)
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
 
@@ -2825,7 +3230,7 @@ void wxWindow::DoAddChild(wxWindow *child)
     (*m_insertCallback)(this, child);
 }
 
-void wxWindow::Raise()
+void wxWindowGTK::Raise()
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2834,7 +3239,7 @@ void wxWindow::Raise()
     gdk_window_raise( m_widget->window );
 }
 
-void wxWindow::Lower()
+void wxWindowGTK::Lower()
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2843,14 +3248,23 @@ void wxWindow::Lower()
     gdk_window_lower( m_widget->window );
 }
 
-bool wxWindow::SetCursor( const wxCursor &cursor )
+bool wxWindowGTK::SetCursor( const wxCursor &cursor )
 {
     wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
 
-    return wxWindowBase::SetCursor( cursor );
+    if (cursor == m_cursor)
+       return FALSE;
+
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (cursor == wxNullCursor)
+       return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
+    else
+       return wxWindowBase::SetCursor( cursor );
 }
 
-void wxWindow::WarpPointer( int x, int y )
+void wxWindowGTK::WarpPointer( int x, int y )
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
@@ -2867,11 +3281,17 @@ void wxWindow::WarpPointer( int x, int y )
         gdk_window_warp_pointer( window, x, y );
 }
 
-void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
+void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
     if (!m_widget) return;
     if (!m_widget->window) return;
 
+    // temporarily hide the caret to avoid nasty interactions between caret
+    // drawing and the window contents redraw
+#if 0 // def wxUSE_CARET -- doesn't seem to help :-(
+    wxCaretSuspend cs((wxWindow *)this);
+#endif // wxUSE_CARET
+
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
     {
         if (rect)
@@ -2893,41 +3313,72 @@ void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
+
+/*
             GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
             gboolean old_clear = pizza->clear_on_draw;
             gtk_pizza_set_clear( pizza, FALSE );
-
             gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
-
             gtk_pizza_set_clear( pizza, old_clear );
+*/
+            GdkEventExpose gdk_event;
+            gdk_event.type = GDK_EXPOSE;
+            gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
+            gdk_event.count = 0;
+            gdk_event.area.x = 0;
+            gdk_event.area.y = 0;
+            gdk_event.area.width = m_wxwindow->allocation.width;
+            gdk_event.area.height = m_wxwindow->allocation.height;
+            gtk_window_expose_callback( m_wxwindow, &gdk_event, (wxWindow *)this );
         }
         else
+        {
             gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
+        }
     }
     else
     {
-        GdkRectangle gdk_rect;
-        gdk_rect.x = rect->x;
-        gdk_rect.y = rect->y;
-        gdk_rect.width = rect->width;
-        gdk_rect.height = rect->height;
 
         if (m_wxwindow)
         {
+/*
             GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
             gboolean old_clear = pizza->clear_on_draw;
             gtk_pizza_set_clear( pizza, FALSE );
 
+            GdkRectangle gdk_rect;
+            gdk_rect.x = rect->x;
+            gdk_rect.y = rect->y;
+            gdk_rect.width = rect->width;
+            gdk_rect.height = rect->height;
             gtk_widget_draw( m_wxwindow, &gdk_rect );
+            gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
 
             gtk_pizza_set_clear( pizza, old_clear );
+*/
+            GdkEventExpose gdk_event;
+            gdk_event.type = GDK_EXPOSE;
+            gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
+            gdk_event.count = 0;
+            gdk_event.area.x = rect->x;
+            gdk_event.area.y = rect->y;
+            gdk_event.area.width = rect->width;
+            gdk_event.area.height = rect->height;
+            gtk_window_expose_callback( m_wxwindow, &gdk_event, (wxWindow *)this );
         }
         else
+        {
+            GdkRectangle gdk_rect;
+            gdk_rect.x = rect->x;
+            gdk_rect.y = rect->y;
+            gdk_rect.width = rect->width;
+            gdk_rect.height = rect->height;
             gtk_widget_draw( m_widget, &gdk_rect );
+        }
     }
 }
 
-void wxWindow::Clear()
+void wxWindowGTK::Clear()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
@@ -2935,26 +3386,26 @@ void wxWindow::Clear()
 
     if (m_wxwindow && m_wxwindow->window)
     {
-        gdk_window_clear( m_wxwindow->window );
+//        gdk_window_clear( m_wxwindow->window );
     }
 }
 
 #if wxUSE_TOOLTIPS
-void wxWindow::DoSetToolTip( wxToolTip *tip )
+void wxWindowGTK::DoSetToolTip( wxToolTip *tip )
 {
     wxWindowBase::DoSetToolTip(tip);
 
     if (m_tooltip)
-        m_tooltip->Apply( this );
+        m_tooltip->Apply( (wxWindow *)this );
 }
 
-void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
+void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
 {
     gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
 }
 #endif // wxUSE_TOOLTIPS
 
-bool wxWindow::SetBackgroundColour( const wxColour &colour )
+bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
 {
     wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
 
@@ -2995,7 +3446,7 @@ bool wxWindow::SetBackgroundColour( const wxColour &colour )
     return TRUE;
 }
 
-bool wxWindow::SetForegroundColour( const wxColour &colour )
+bool wxWindowGTK::SetForegroundColour( const wxColour &colour )
 {
     wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
 
@@ -3025,13 +3476,18 @@ bool wxWindow::SetForegroundColour( const wxColour &colour )
     return TRUE;
 }
 
-GtkStyle *wxWindow::GetWidgetStyle()
+GtkStyle *wxWindowGTK::GetWidgetStyle()
 {
     if (m_widgetStyle)
     {
         GtkStyle *remake = gtk_style_copy( m_widgetStyle );
+#ifdef __WXGTK20__
+        /* FIXME: is this necessary? */
+        _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
+#else
         remake->klass = m_widgetStyle->klass;
-        
+#endif
+
         gtk_style_unref( m_widgetStyle );
         m_widgetStyle = remake;
     }
@@ -3043,14 +3499,33 @@ GtkStyle *wxWindow::GetWidgetStyle()
             def = gtk_widget_get_default_style();
 
         m_widgetStyle = gtk_style_copy( def );
+#ifdef __WXGTK20__
+        /* FIXME: is this necessary? */
+        _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
+#else
         m_widgetStyle->klass = def->klass;
+#endif
     }
 
     return m_widgetStyle;
 }
 
-void wxWindow::SetWidgetStyle()
+void wxWindowGTK::SetWidgetStyle()
 {
+#if DISABLE_STYLE_IF_BROKEN_THEM
+    if (m_widget->style->engine_data)
+    {
+        static bool s_warningPrinted = FALSE;
+        if (!s_warningPrinted)
+        {
+            printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
+            s_warningPrinted = TRUE;
+        }
+        m_widgetStyle = m_widget->style;
+        return;
+    }
+#endif
+
     GtkStyle *style = GetWidgetStyle();
 
     if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
@@ -3068,6 +3543,21 @@ void wxWindow::SetWidgetStyle()
             style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
             style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
         }
+        else
+        {
+            // Try to restore the gtk default style.  This is still a little
+            // oversimplified for what is probably really needed here for controls
+            // other than buttons, but is better than not being able to (re)set a
+            // control's foreground colour to *wxBLACK -- RL
+            GtkStyle *def = gtk_rc_get_style( m_widget );
+
+            if (!def)
+                def = gtk_widget_get_default_style();
+
+            style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
+            style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
+            style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
+        }
     }
 
     if (m_backgroundColour.Ok())
@@ -3083,11 +3573,33 @@ void wxWindow::SetWidgetStyle()
             style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
             style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
             style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
-       }
+        }
+        else
+        {
+            // Try to restore the gtk default style.  This is still a little
+            // oversimplified for what is probably really needed here for controls
+            // other than buttons, but is better than not being able to (re)set a
+            // control's background colour to default grey and means resetting a
+            // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
+            // behavior -- RL
+            GtkStyle *def = gtk_rc_get_style( m_widget );
+
+            if (!def)
+                def = gtk_widget_get_default_style();
+
+            style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
+            style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
+            style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
+            style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
+            style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
+            style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
+            style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
+            style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
+        }
     }
 }
 
-void wxWindow::ApplyWidgetStyle()
+void wxWindowGTK::ApplyWidgetStyle()
 {
 }
 
@@ -3095,12 +3607,14 @@ void wxWindow::ApplyWidgetStyle()
 // Pop-up menu stuff
 //-----------------------------------------------------------------------------
 
+#if wxUSE_MENUS_NATIVE
+
 static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting  )
 {
     *is_waiting = FALSE;
 }
 
-static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
+static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
 {
     menu->SetInvokingWindow( win );
     wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
@@ -3121,14 +3635,14 @@ static gint gs_pop_y = 0;
 
 static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
                               gint *x, gint *y,
-                              wxWindow *win )
+                              wxWindowGTK *win )
 {
     win->ClientToScreen( &gs_pop_x, &gs_pop_y );
     *x = gs_pop_x;
     *y = gs_pop_y;
 }
 
-bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
+bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 {
     wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
 
@@ -3165,9 +3679,11 @@ bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
     return TRUE;
 }
 
+#endif // wxUSE_MENUS_NATIVE
+
 #if wxUSE_DRAG_AND_DROP
 
-void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
+void wxWindowGTK::SetDropTarget( wxDropTarget *dropTarget )
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
@@ -3183,7 +3699,7 @@ void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
 
 #endif // wxUSE_DRAG_AND_DROP
 
-GtkWidget* wxWindow::GetConnectWidget()
+GtkWidget* wxWindowGTK::GetConnectWidget()
 {
     GtkWidget *connect_widget = m_widget;
     if (m_wxwindow) connect_widget = m_wxwindow;
@@ -3191,7 +3707,7 @@ GtkWidget* wxWindow::GetConnectWidget()
     return connect_widget;
 }
 
-bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
+bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window )
 {
     if (m_wxwindow)
         return (window == GTK_PIZZA(m_wxwindow)->bin_window);
@@ -3199,7 +3715,7 @@ bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
     return (window == m_widget->window);
 }
 
-bool wxWindow::SetFont( const wxFont &font )
+bool wxWindowGTK::SetFont( const wxFont &font )
 {
     wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
 
@@ -3223,19 +3739,21 @@ bool wxWindow::SetFont( const wxFont &font )
     return TRUE;
 }
 
-void wxWindow::CaptureMouse()
+void wxWindowGTK::CaptureMouse()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
-    wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
-
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
         window = GTK_PIZZA(m_wxwindow)->bin_window;
     else
         window = GetConnectWidget()->window;
 
-    if (!window) return;
+    wxCHECK_RET( window, _T("CaptureMouse() failed") );
+
+    wxCursor* cursor = & m_cursor;
+    if (!cursor->Ok())
+        cursor = wxSTANDARD_CURSOR;
 
     gdk_pointer_grab( window, FALSE,
                       (GdkEventMask)
@@ -3244,16 +3762,17 @@ void wxWindow::CaptureMouse()
                           GDK_POINTER_MOTION_HINT_MASK |
                           GDK_POINTER_MOTION_MASK),
                       (GdkWindow *) NULL,
-                      m_cursor.GetCursor(),
+                      cursor->GetCursor(),
                       (guint32)GDK_CURRENT_TIME );
     g_captureWindow = this;
+    g_captureWindowHasMouse = TRUE;
 }
 
-void wxWindow::ReleaseMouse()
+void wxWindowGTK::ReleaseMouse()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
-    wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
+    wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") );
 
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
@@ -3265,15 +3784,21 @@ void wxWindow::ReleaseMouse()
         return;
 
     gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
-    g_captureWindow = (wxWindow*) NULL;
+    g_captureWindow = (wxWindowGTK*) NULL;
+}
+
+/* static */
+wxWindow *wxWindowBase::GetCapture()
+{
+    return (wxWindow *)g_captureWindow;
 }
 
-bool wxWindow::IsRetained() const
+bool wxWindowGTK::IsRetained() const
 {
     return FALSE;
 }
 
-void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
+void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
       int range, bool refresh )
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
@@ -3332,28 +3857,12 @@ void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
     }
 
     if (orient == wxHORIZONTAL)
-    {
-        gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
-            (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
-    
         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
-        
-        gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
-            (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
-    }
     else
-    {
-        gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
-            (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
-
         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
-        
-        gtk_signal_connect( GTK_OBJECT(m_vAdjust), "changed",
-            (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
-    }
 }
 
-void wxWindow::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") );
 
@@ -3386,9 +3895,9 @@ void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
         {
             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
                 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
-                
+
             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
-            
+
             gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
                 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
         }
@@ -3396,7 +3905,7 @@ void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
         {
             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
                 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
-        
+
             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
 
             gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
@@ -3405,7 +3914,7 @@ void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
     }
 }
 
-int wxWindow::GetScrollThumb( int orient ) const
+int wxWindowGTK::GetScrollThumb( int orient ) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
 
@@ -3417,7 +3926,7 @@ int wxWindow::GetScrollThumb( int orient ) const
         return (int)(m_vAdjust->page_size+0.5);
 }
 
-int wxWindow::GetScrollPos( int orient ) const
+int wxWindowGTK::GetScrollPos( int orient ) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
 
@@ -3429,7 +3938,7 @@ int wxWindow::GetScrollPos( int orient ) const
         return (int)(m_vAdjust->value+0.5);
 }
 
-int wxWindow::GetScrollRange( int orient ) const
+int wxWindowGTK::GetScrollRange( int orient ) const
 {
     wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
 
@@ -3441,67 +3950,109 @@ int wxWindow::GetScrollRange( int orient ) const
         return (int)(m_vAdjust->upper+0.5);
 }
 
-void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
+void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
 
-/*
-    printf( "ScrollWindow: %d %d\n", dx, dy );
-*/
+    if ((dx == 0) && (dy == 0)) return;
 
+    m_clipPaintRegion = TRUE;
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
+    m_clipPaintRegion = FALSE;
 
 /*
-    if (!m_scrollGC)
+    if (m_children.GetCount() > 0)
     {
-        m_scrollGC = gdk_gc_new( m_wxwindow->window );
-        gdk_gc_set_exposures( m_scrollGC, TRUE );
+        gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
     }
-
-    wxNode *node = m_children.First();
-    while (node)
+    else
     {
-        wxWindow *child = (wxWindow*) node->Data();
-        int sx = 0;
-        int sy = 0;
-        child->GetSize( &sx, &sy );
-        child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
-        node = node->Next();
-    }
+        GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
 
-    int cw = 0;
-    int ch = 0;
-    GetClientSize( &cw, &ch );
-    int w = cw - abs(dx);
-    int h = ch - abs(dy);
+        pizza->xoffset -= dx;
+        pizza->yoffset -= dy;
 
-    if ((h < 0) || (w < 0))
-    {
-        Refresh();
-    }
-    else
-    {
-        int s_x = 0;
-        int s_y = 0;
-        if (dx < 0) s_x = -dx;
-        if (dy < 0) s_y = -dy;
-        int d_x = 0;
-        int d_y = 0;
-        if (dx > 0) d_x = dx;
-        if (dy > 0) d_y = dy;
+        GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
+        gdk_gc_set_exposures( m_scrollGC, TRUE );
 
-        gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
-            m_wxwindow->window, s_x, s_y, w, h );
+        int cw = 0;
+        int ch = 0;
+        GetClientSize( &cw, &ch );
+        int w = cw - abs(dx);
+        int h = ch - abs(dy);
 
-        wxRect rect;
-        if (dx < 0) rect.x = cw+dx; else rect.x = 0;
-        if (dy < 0) rect.y = ch+dy; else rect.y = 0;
-        if (dy != 0) rect.width = cw; else rect.width = abs(dx);
-        if (dx != 0) rect.height = ch; else rect.height = abs(dy);
+        if ((h < 0) || (w < 0))
+        {
+            Refresh();
+        }
+        else
+        {
+            int s_x = 0;
+            int s_y = 0;
+            if (dx < 0) s_x = -dx;
+            if (dy < 0) s_y = -dy;
+            int d_x = 0;
+            int d_y = 0;
+            if (dx > 0) d_x = dx;
+            if (dy > 0) d_y = dy;
+
+            gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
+                pizza->bin_window, s_x, s_y, w, h );
+
+            wxRect rect;
+            if (dx < 0) rect.x = cw+dx; else rect.x = 0;
+            if (dy < 0) rect.y = ch+dy; else rect.y = 0;
+            if (dy != 0) rect.width = cw; else rect.width = abs(dx);
+            if (dx != 0) rect.height = ch; else rect.height = abs(dy);
+
+            Refresh( TRUE, &rect );
+        }
 
-        Refresh( TRUE, &rect );
+        gdk_gc_unref( m_scrollGC );
     }
 */
 }
+
+// Find the wxWindow at the current mouse position, also returning the mouse
+// position.
+wxWindow* wxFindWindowAtPointer(wxPoint& pt)
+{
+    pt = wxGetMousePosition();
+    wxWindow* found = wxFindWindowAtPoint(pt);
+    return found;
+}
+
+// Get the current mouse position.
+wxPoint wxGetMousePosition()
+{
+  /* This crashes when used within wxHelpContext,
+     so we have to use the X-specific implementation below.
+    gint x, y;
+    GdkModifierType *mask;
+    (void) gdk_window_get_pointer(NULL, &x, &y, mask);
+
+    return wxPoint(x, y);
+  */
+
+    int x, y;
+    GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
+    if (!windowAtPtr)
+      return wxPoint(-999, -999);
+
+    Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
+    Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
+    Window rootReturn, childReturn;
+    int rootX, rootY, winX, winY;
+    unsigned int maskReturn;
+
+    XQueryPointer (display,
+           rootWindow,
+           &rootReturn,
+                   &childReturn,
+                   &rootX, &rootY, &winX, &winY, &maskReturn);
+    return wxPoint(rootX, rootY);
+
+}
+