]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
Made dnd reentrent safe as per stable tree.
[wxWidgets.git] / src / gtk1 / window.cpp
index 5e09f6f528311003e350e0ab6d8b067d4b9d6544..a85d6ab17b857ad6d222173471a3f122b5be095b 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/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
 //-----------------------------------------------------------------------------
@@ -208,6 +219,8 @@ extern bool g_mainThreadLocked;
 // debug
 //-----------------------------------------------------------------------------
 
+#define DISABLE_STYLE_IF_BROKEN_THEME 1
+
 #ifdef __WXDEBUG__
 
 #if wxUSE_THREADS
@@ -265,11 +278,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 +305,7 @@ gdk_window_warp_pointer (GdkWindow      *window,
                     0, 0, 0, 0,        /* not source window -> move from anywhere */
                     x, y );
   }
+#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -293,6 +319,28 @@ extern bool g_isIdle;
 // local code (see below)
 //-----------------------------------------------------------------------------
 
+// returns the child of win which currently has focus or NULL if not found
+static wxWindow *FindFocusedChild(wxWindow *win)
+{
+    wxWindow *winFocus = wxWindow::FindFocus();
+    if ( !winFocus )
+        return (wxWindow *)NULL;
+
+    if ( winFocus == win )
+        return win;
+
+    for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxWindow *child = FindFocusedChild(node->GetData());
+        if ( child )
+            return child;
+    }
+
+    return (wxWindow *)NULL;
+}
+
 static void draw_frame( GtkWidget *widget, wxWindow *win )
 {
     if (!win->m_hasVMT)
@@ -308,16 +356,16 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
             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)
             {
@@ -379,10 +427,13 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
 // "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, wxWindow *win )
 {
-    if (gdk_event->count > 0) return;
+    if (gdk_event->count > 0) return FALSE;
+    
     draw_frame( widget, win );
+    
+    return TRUE;
 }
 
 //-----------------------------------------------------------------------------
@@ -495,7 +546,7 @@ static long map_to_unmodified_wx_keysym( KeySym keysym )
         case GDK_F12:           key_code = WXK_F12;         break;
         default:
         {
-            if (keysym <= 0xFF)
+            if ((keysym & 0xF000) == 0)
             {
                 guint upper = gdk_keyval_to_upper( (guint)keysym );
                 keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
@@ -594,7 +645,7 @@ static long map_to_wx_keysym( KeySym keysym )
         case GDK_F12:           key_code = WXK_F12;         break;
         default:
         {
-            if (keysym <= 0xFF)
+            if ((keysym & 0xF000) == 0)
             {
                 key_code = (guint)keysym;
             }
@@ -608,79 +659,189 @@ static long map_to_wx_keysym( KeySym keysym )
 // "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)
+    {
+        wxEraseEvent eevent( win->GetId() );
+        eevent.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent(eevent);
 
-    if (gdk_event->count > 0)
-        return;
+        wxPaintEvent event( win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
+        
+        win->GetUpdateRegion().Clear();
+    }
+    
+        /* 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;
 
-    wxEraseEvent eevent( win->GetId() );
-    eevent.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent(eevent);
+            GdkEventExpose child_event = *gdk_event;
 
-    wxPaintEvent event( win->GetId() );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( 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;
+}
 
-    win->GetUpdateRegion().Clear();
+//-----------------------------------------------------------------------------
+// "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)
-        return;
-
-    win->GetUpdateRegion().Union( rect->x, rect->y,
-                                  rect->width, rect->height );
+    // this is supposed to take care of extra (and unneeded) frame repaints
+    if (win->GetChildren().GetCount() == 0)
+        return; 
 
 /*
-    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 );
+    }
 */
+   
+    GtkPizza *pizza = GTK_PIZZA (widget);
 
-    wxEraseEvent eevent( win->GetId() );
-    eevent.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent(eevent);
+    if (win->GetThemeEnabled())
+    {
+        wxWindow *parent = win->GetParent();
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+        if (!parent)
+            parent = win;
 
-    wxPaintEvent event( win->GetId() );
-    event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
+        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;
+    
+        wxEraseEvent eevent( win->GetId() );
+        eevent.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent(eevent);
+
+        wxPaintEvent event( win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
 
-    win->GetUpdateRegion().Clear();
+        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*/ );
+            }
+        }
 }
 
 //-----------------------------------------------------------------------------
@@ -697,6 +858,7 @@ 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;
@@ -741,7 +903,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();
         }
@@ -773,7 +935,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)) )
     {
@@ -1396,6 +1563,15 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(
         gdk_im_begin(win->m_ic, win->m_wxwindow->window);
 #endif
 
+#ifdef wxUSE_CARET
+    // caret needs to be informed about focus change
+    wxCaret *caret = win->GetCaret();
+    if ( caret )
+    {
+        caret->OnSetFocus();
+    }
+#endif // wxUSE_CARET
+
     wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
     event.SetEventObject( win );
 
@@ -1427,6 +1603,10 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
     // g_sendActivateEvent to -1
     g_sendActivateEvent = 0;
 
+    wxWindow *winFocus = FindFocusedChild(win);
+    if ( winFocus )
+        win = winFocus;
+
     g_focusWindow = (wxWindow *)NULL;
 
 /*
@@ -1441,6 +1621,15 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
         gdk_im_end();
 #endif
 
+#ifdef wxUSE_CARET
+    // caret needs to be informed about focus change
+    wxCaret *caret = win->GetCaret();
+    if ( caret )
+    {
+        caret->OnKillFocus();
+    }
+#endif // wxUSE_CARET
+
     wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
     event.SetEventObject( win );
 
@@ -1633,6 +1822,7 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
     if (g_isIdle)
         wxapp_install_idle_handler();
 
+
     g_blockEventsOnScroll = TRUE;
     win->m_isScrolling = (gdk_event->window == widget->slider);
 
@@ -1658,7 +1848,7 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
 
     if (win->m_isScrolling)
     {
-        wxEventType command = wxEVT_SCROLL_THUMBRELEASE;
+        wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
         int value = -1;
         int dir = -1;
 
@@ -1718,7 +1908,7 @@ gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
-
+    
     return FALSE;
 }
 
@@ -1829,8 +2019,8 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
     if ((colormap = gtk_widget_get_colormap (widget)) !=
            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;
@@ -1962,8 +2152,13 @@ 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;
@@ -1996,22 +2191,13 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
     }
 
     m_insertCallback = wxInsertChildInWindow;
-
+    
     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 );
@@ -2021,10 +2207,6 @@ 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 );
 
 #if (GTK_MINOR_VERSION > 0)
@@ -2147,10 +2329,11 @@ wxWindow::~wxWindow()
 
     if (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;
     }
 
@@ -2208,6 +2391,12 @@ 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), "event",
+                GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
+
             gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
                 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
 
@@ -2317,7 +2506,7 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
 
     if (m_resizing) return; /* I don't like recursions */
     m_resizing = TRUE;
-
+    
     if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
     {
         /* don't set the size for children of wxNotebook, just take the values. */
@@ -2378,6 +2567,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 );
     }
 
@@ -2491,16 +2686,16 @@ void wxWindow::DoSetClientSize( int width, int height )
             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)
             {
@@ -2553,16 +2748,16 @@ void wxWindow::DoGetClientSize( int *width, int *height ) const
             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)
             {
@@ -2839,7 +3034,16 @@ bool wxWindow::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 )
@@ -2885,37 +3089,69 @@ 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, 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, 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 );
+        }
     }
 }
 
@@ -2927,7 +3163,7 @@ void wxWindow::Clear()
 
     if (m_wxwindow && m_wxwindow->window)
     {
-        gdk_window_clear( m_wxwindow->window );
+//        gdk_window_clear( m_wxwindow->window );
     }
 }
 
@@ -3022,7 +3258,12 @@ GtkStyle *wxWindow::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;
@@ -3035,7 +3276,12 @@ 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;
@@ -3043,6 +3289,7 @@ GtkStyle *wxWindow::GetWidgetStyle()
 
 void wxWindow::SetWidgetStyle()
 {
+#if DISABLE_STYLE_IF_BROKEN_THEM
     if (m_widget->style->engine_data)
     {
         static bool s_warningPrinted = FALSE;
@@ -3054,6 +3301,7 @@ void wxWindow::SetWidgetStyle()
         m_widgetStyle = m_widget->style;
         return;
     }
+#endif
 
     GtkStyle *style = GetWidgetStyle();
 
@@ -3072,6 +3320,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())
@@ -3087,7 +3350,29 @@ 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];
+        }
     }
 }
 
@@ -3241,6 +3526,10 @@ void wxWindow::CaptureMouse()
 
     if (!window) return;
 
+    wxCursor* cursor = & m_cursor;
+    if (!cursor->Ok())
+        cursor = wxSTANDARD_CURSOR;
+
     gdk_pointer_grab( window, FALSE,
                       (GdkEventMask)
                          (GDK_BUTTON_PRESS_MASK |
@@ -3248,7 +3537,7 @@ 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;
 }
@@ -3434,62 +3723,104 @@ void wxWindow::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") );
+    
+    if ((dx == 0) && (dy == 0)) return;
 
-/*
-    printf( "ScrollWindow: %d %d\n", dx, dy );
-*/
-
+    m_clipPaintRegion = TRUE;
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
-
-/*
-    if (!m_scrollGC)
+    m_clipPaintRegion = FALSE;
+    
+/*    
+    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);
+    
+        pizza->xoffset -= dx;
+        pizza->yoffset -= dy;
+        
+        GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
+        gdk_gc_set_exposures( m_scrollGC, TRUE );
 
-    int cw = 0;
-    int ch = 0;
-    GetClientSize( &cw, &ch );
-    int w = cw - abs(dx);
-    int h = ch - abs(dy);
+        int cw = 0;
+        int ch = 0;
+        GetClientSize( &cw, &ch );
+        int w = cw - abs(dx);
+        int h = ch - abs(dy);
 
-    if ((h < 0) || (w < 0))
-    {
-        Refresh();
+        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 );
+        }
+        
+        gdk_gc_unref( m_scrollGC );
     }
-    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( m_wxwindow->window, m_scrollGC, d_x, d_y,
-            m_wxwindow->window, s_x, s_y, w, h );
+// 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;
+}
 
-        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);
+// 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);
 
-        Refresh( TRUE, &rect );
-    }
-*/
 }
+