]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
Use "&Help" so wxMac doesn't make an extra help menu
[wxWidgets.git] / src / gtk1 / window.cpp
index c12e2fad49b8c4689ca166ebab05835f4e0d02d8..5eee285dc35c9fa7f4c301c2335d235833560b3c 100644 (file)
@@ -8,15 +8,17 @@
 /////////////////////////////////////////////////////////////////////////////
 
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "window.h"
 #endif
 
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
 #ifdef __VMS
 #define XWarpPointer XWARPPOINTER
 #endif
 
-#include "wx/defs.h"
 #include "wx/window.h"
 #include "wx/dcclient.h"
 #include "wx/frame.h"
@@ -48,6 +50,7 @@
 #include "wx/intl.h"
 #include "wx/settings.h"
 #include "wx/log.h"
+#include "wx/fontutil.h"
 
 #ifdef __WXDEBUG__
     #include "wx/thread.h"
 
 #include "wx/gtk/win_gtk.h"
 
+#ifdef __WXGTK20__
+#include <pango/pangox.h>
+#endif
+
 #ifdef __WXGTK20__
     #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
 #else
@@ -250,9 +257,9 @@ wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL;
 // send any activate events at all
 static int        g_sendActivateEvent = -1;
 
-/* hack: we need something to pass to gtk_menu_popup, so we store the time of
-   the last click here */
-static guint32 gs_timeLastClick = 0;
+// hack: we need something to pass to gtk_menu_popup, so we store the time of
+// the last click here
+static guint32 gs_timeLastClick = 0; 
 
 extern bool g_mainThreadLocked;
 
@@ -261,7 +268,7 @@ extern bool g_mainThreadLocked;
 //-----------------------------------------------------------------------------
 
 #ifndef __WXGTK20__
-#define DISABLE_STYLE_IF_BROKEN_THEME 1
+#define DISABLE_STYLE_IF_BROKEN_THEME 0
 #endif
 
 #ifdef __WXDEBUG__
@@ -340,7 +347,7 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win)
     if ( winFocus == win )
         return (wxWindow *)win;
 
-    for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+    for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
           node;
           node = node->GetNext() )
     {
@@ -472,12 +479,18 @@ static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNU
 // "size_request" of m_widget
 //-----------------------------------------------------------------------------
 
-static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
+// make it extern because wxStatitText needs to disconnect this one
+extern "C"
+void wxgtk_window_size_request_callback(GtkWidget *widget,
+                                        GtkRequisition *requisition,
+                                        wxWindow *win)
 {
-    int w,h;
+    int w, h;
     win->GetSize( &w, &h );
-    if (w < 2) w = 2;
-    if (h < 2) h = 2;
+    if (w < 2)
+        w = 2;
+    if (h < 2)
+        h = 2;
 
     requisition->height = h;
     requisition->width = w;
@@ -496,6 +509,14 @@ static int gtk_window_expose_callback( GtkWidget *widget,
     if (g_isIdle)
         wxapp_install_idle_handler();
 
+#ifdef __WXGTK20__
+    // This callback gets called in drawing-idle time under
+    // GTK 2.0, so we don't need to defer anything to idle
+    // time anymore.
+
+    GtkPizza *pizza = GTK_PIZZA( widget );
+    if (gdk_event->window != pizza->bin_window) return FALSE;
+
 #if 0
     if (win->GetName())
     {
@@ -507,8 +528,32 @@ static int gtk_window_expose_callback( GtkWidget *widget,
                                          (int)gdk_event->area.width,
                                          (int)gdk_event->area.height );
     }
+    
+    gtk_paint_box
+    (
+        win->m_wxwindow->style,
+        pizza->bin_window,
+        GTK_STATE_NORMAL,
+        GTK_SHADOW_OUT,
+        (GdkRectangle*) NULL,
+        win->m_wxwindow,
+        (char *)"button", // const_cast
+        20,20,24,24
+    );
 #endif
 
+    win->GetUpdateRegion() = wxRegion( gdk_event->region );
+
+    win->GtkSendPaintEvents();
+
+
+    // Let parent window draw window less widgets
+    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
+#else
+    // This gets called immediately after an expose event
+    // under GTK 1.2 so we collect the calls and wait for
+    // the idle handler to pick things up.
+
     win->GetUpdateRegion().Union( gdk_event->area.x,
                                   gdk_event->area.y,
                                   gdk_event->area.width,
@@ -520,14 +565,9 @@ static int gtk_window_expose_callback( GtkWidget *widget,
 
     // Actual redrawing takes place in idle time.
     // win->GtkUpdate();
-
-#ifdef __WXGTK20__
-
-    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-
 #endif
 
-    return TRUE;
+    return FALSE;
 }
 
 //-----------------------------------------------------------------------------
@@ -571,10 +611,11 @@ static void gtk_window_draw_callback( GtkWidget *widget,
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
-    // there are no child windows.
-    if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
-        (win->GetChildren().GetCount() == 0))
+    // if there are any children we must refresh everything
+    //
+    // VZ: why?
+    if ( !win->HasFlag(wxFULL_REPAINT_ON_RESIZE) &&
+            win->GetChildren().IsEmpty() )
     {
         return;
     }
@@ -1045,6 +1086,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
     return TRUE;
 }
 
+
 static gint gtk_window_key_press_callback( GtkWidget *widget,
                                            GdkEventKey *gdk_event,
                                            wxWindow *win )
@@ -1094,42 +1136,58 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     // will only be sent if it is not in an accelerator table.
     if (!ret)
     {
-        // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+        long key_code;
         KeySym keysym = gdk_event->keyval;
-        long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
-        if ( !key_code )
+#ifdef __WXGTK20__
+        // In GTK 2.0, we need to hand over the key event to an input method
+        // and the IM will emit a "commit" event containing the actual utf8
+        // character.  In that case the EVT_CHAR events will be sent from
+        // there.  But only do it this way for non-KeySym keys.
+        key_code = wxTranslateKeySymToWXKey(gdk_event->keyval, FALSE /* isChar */);
+        if ( !key_code && win->m_imContext )
         {
-            if ( gdk_event->length == 1 )
-            {
-                key_code = (unsigned char)gdk_event->string[0];
-            }
-            else if ( wxIsAsciiKeysym(keysym) )
-            {
-                // ASCII key
-                key_code = (unsigned char)keysym;
-            }
+            gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
+            ret = TRUE;
         }
-
-        if ( key_code )
+        else
+#endif
         {
-            wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
-
-            event.m_keyCode = key_code;
-            
-            // Implement OnCharHook by checking ancesteror top level windows
-            wxWindow *parent = win;
-            while (parent && !parent->IsTopLevel())
-            parent = parent->GetParent();
-            if (parent)
+            // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+            key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
+            if ( !key_code )
             {
-                event.SetEventType( wxEVT_CHAR_HOOK );
-                ret = parent->GetEventHandler()->ProcessEvent( event );
+                if ( gdk_event->length == 1 )
+                {
+                    key_code = (unsigned char)gdk_event->string[0];
+                }
+                else if ( wxIsAsciiKeysym(keysym) )
+                {
+                    // ASCII key
+                    key_code = (unsigned char)keysym;
+                }
             }
 
-            if (!ret)
+            if ( key_code )
             {
-                event.SetEventType(wxEVT_CHAR);
-                ret = win->GetEventHandler()->ProcessEvent( event );
+                wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
+
+                event.m_keyCode = key_code;
+
+                // Implement OnCharHook by checking ancesteror top level windows
+                wxWindow *parent = win;
+                while (parent && !parent->IsTopLevel())
+                    parent = parent->GetParent();
+                if (parent)
+                {
+                    event.SetEventType( wxEVT_CHAR_HOOK );
+                    ret = parent->GetEventHandler()->ProcessEvent( event );
+                }
+
+                if (!ret)
+                {
+                    event.SetEventType(wxEVT_CHAR);
+                    ret = win->GetEventHandler()->ProcessEvent( event );
+                }
             }
         }
     }
@@ -1159,50 +1217,95 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     if ( !ret &&
          (gdk_event->keyval == GDK_Escape) )
     {
-        wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
-        new_event.SetEventObject( win );
-        ret = win->GetEventHandler()->ProcessEvent( new_event );
-    }
-
-    // Doesn't work.
-#if 0 
-    // Pressing F10 will activate the menu bar of the top frame
-    if ( (!ret) &&
-         (gdk_event->keyval == GDK_F10) )
-    {
-        wxWindowGTK *ancestor = win;
-        while (ancestor)
+        // however only do it if we have a Cancel button in the dialog,
+        // otherwise the user code may get confused by the events from a
+        // non-existing button and, worse, a wxButton might get button event
+        // from another button which is not really expected
+        wxWindow *winForCancel = win,
+                 *btnCancel = NULL;
+        while ( winForCancel )
         {
-            if (wxIsKindOf(ancestor,wxFrame))
+            btnCancel = winForCancel->FindWindow(wxID_CANCEL);
+            if ( btnCancel )
             {
-                wxFrame *frame = (wxFrame*) ancestor;
-                wxMenuBar *menubar = frame->GetMenuBar();
-                if (menubar)
-                {
-                    wxNode *node = menubar->GetMenus().First();
-                    if (node)
-                    {
-                        wxMenu *firstMenu = (wxMenu*) node->Data();
-                        gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
-                        ret = TRUE;
-                        break;
-                    }
-                }
+                // found a cancel button
+                break;
             }
-            ancestor = ancestor->GetParent();
+
+            if ( winForCancel->IsTopLevel() )
+            {
+                // no need to look further
+                break;
+            }
+
+            // maybe our parent has a cancel button?
+            winForCancel = winForCancel->GetParent();
+        }
+
+        if ( btnCancel )
+        {
+            wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
+            event.SetEventObject(btnCancel);
+            ret = btnCancel->GetEventHandler()->ProcessEvent(event);
         }
     }
-#endif // 0
 
     if (ret)
     {
         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
         return TRUE;
     }
-    
+
     return FALSE;
 }
 
+#ifdef __WXGTK20__
+static void gtk_wxwindow_commit_cb (GtkIMContext *context,
+                           const gchar  *str,
+                           wxWindow     *window)
+{
+    bool ret = FALSE;
+
+    wxKeyEvent event( wxEVT_KEY_DOWN );
+
+#if wxUSE_UNICODE
+    event.m_uniChar = g_utf8_get_char( str );
+
+    // Backward compatible for ISO-8859
+    if (event.m_uniChar < 256)
+        event.m_keyCode = event.m_uniChar;
+#else
+    gunichar uniChar = g_utf8_get_char( str );
+    // We cannot handle Unicode in non-Unicode mode
+    if (uniChar > 255) return;
+
+    event.m_keyCode = uniChar;
+#endif
+
+
+    // TODO:  We still need to set all the extra attributes of the
+    //        event, modifiers and such...
+
+
+    // Implement OnCharHook by checking ancestor top level windows
+    wxWindow *parent = window;
+    while (parent && !parent->IsTopLevel())
+        parent = parent->GetParent();
+    if (parent)
+    {
+        event.SetEventType( wxEVT_CHAR_HOOK );
+        ret = parent->GetEventHandler()->ProcessEvent( event );
+    }
+
+    if (!ret)
+    {
+        event.SetEventType(wxEVT_CHAR);
+        ret = window->GetEventHandler()->ProcessEvent( event );
+    }
+}
+#endif
+
+
 //-----------------------------------------------------------------------------
 // "key_release_event" from any window
 //-----------------------------------------------------------------------------
@@ -1260,6 +1363,14 @@ static gint gtk_window_key_release_callback( GtkWidget *widget,
     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);                \
+    if (event.GetEventType()==wxEVT_MOUSEWHEEL)                               \
+    {                                                                         \
+       event.m_linesPerAction = 3;                                            \
+       if (((GdkEventButton*)gdk_event)->button == 4)                         \
+           event.m_wheelRotation = 120;                                       \
+       else if (((GdkEventButton*)gdk_event)->button == 5)                    \
+           event.m_wheelRotation = -120;                                      \
+    }                                                                         \
                                                                               \
     wxPoint pt = win->GetClientAreaOrigin();                                  \
     event.m_x = (wxCoord)gdk_event->x - pt.x;                                 \
@@ -1316,12 +1427,12 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
         yy += pizza->yoffset;
     }
 
-    wxNode *node = win->GetChildren().First();
+    wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
     while (node)
     {
-        wxWindowGTK *child = (wxWindowGTK*)node->Data();
+        wxWindowGTK *child = node->GetData();
 
-        node = node->Next();
+        node = node->GetNext();
         if (!child->IsShown())
             continue;
 
@@ -1331,7 +1442,7 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
             int xx1 = child->m_x;
             int yy1 = child->m_y;
             int xx2 = child->m_x + child->m_width;
-            int yy2 = child->m_x + child->m_height;
+            int yy2 = child->m_y + child->m_height;
 
             // left
             if (((xx >= xx1) && (xx <= xx1+10) && (yy >= yy1) && (yy <= yy2)) ||
@@ -1404,33 +1515,107 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
 */
     }
 
+    // GDK sends surplus button down event
+    // before a double click event. We
+    // need to filter these out.
+    if (gdk_event->type == GDK_BUTTON_PRESS)
+    {
+        GdkEvent *peek_event = gdk_event_peek();
+        if (peek_event)
+        {
+            if ((peek_event->type == GDK_2BUTTON_PRESS) ||
+                (peek_event->type == GDK_3BUTTON_PRESS))
+            {
+                gdk_event_free( peek_event );
+                return TRUE;
+            }
+            else
+            {
+                gdk_event_free( peek_event );
+            }
+        }
+    }
+
     wxEventType event_type = wxEVT_NULL;
 
+    // GdkDisplay is a GTK+ 2.1.0 thing
+#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 1, 0)
+    if ( gdk_event->type == GDK_2BUTTON_PRESS &&
+            gdk_event->button >= 1 && gdk_event->button <= 3 )
+    {
+        // Reset GDK internal timestamp variables in order to disable GDK
+        // triple click events. GDK will then next time believe no button has
+        // been clicked just before, and send a normal button click event.
+        GdkDisplay* display = gtk_widget_get_display (widget);
+        display->button_click_time[1] = 0;
+        display->button_click_time[0] = 0;
+    }
+#endif // GTK 2+
+
     if (gdk_event->button == 1)
     {
+        // note that GDK generates triple click events which are not supported
+        // by wxWindows but still have to be passed to the app as otherwise
+        // clicks would simply go missing
         switch (gdk_event->type)
         {
-            case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
-            case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
-            default:  break;
+            // we shouldn't get triple clicks at all for GTK2 because we
+            // suppress them artificially using the code above but we still
+            // should map them to something for GTK1 and not just ignore them
+            // as this would lose clicks
+            case GDK_3BUTTON_PRESS:     // we could also map this to DCLICK...
+            case GDK_BUTTON_PRESS:
+                event_type = wxEVT_LEFT_DOWN;
+                break;
+
+            case GDK_2BUTTON_PRESS:
+                event_type = wxEVT_LEFT_DCLICK;
+                break;
+
+            default:
+                // just to silence gcc warnings
+                ;
         }
     }
     else if (gdk_event->button == 2)
     {
         switch (gdk_event->type)
         {
-            case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
-            case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
-            default:  break;
+            case GDK_3BUTTON_PRESS:
+            case GDK_BUTTON_PRESS:
+                event_type = wxEVT_MIDDLE_DOWN;
+                break;
+
+            case GDK_2BUTTON_PRESS:
+                event_type = wxEVT_MIDDLE_DCLICK;
+                break;
+
+            default:
+                ;
         }
     }
     else if (gdk_event->button == 3)
     {
         switch (gdk_event->type)
         {
-            case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
-            case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
-            default:  break;
+            case GDK_3BUTTON_PRESS:
+            case GDK_BUTTON_PRESS:
+                event_type = wxEVT_RIGHT_DOWN;
+                break;
+
+            case GDK_2BUTTON_PRESS:
+                event_type = wxEVT_RIGHT_DCLICK;
+                break;
+
+            default:
+                ;
+        }
+    }
+    else if (gdk_event->button == 4 || gdk_event->button == 5)
+    {
+        if (gdk_event->type == GDK_BUTTON_PRESS )
+        {
+            event_type = wxEVT_MOUSEWHEEL;
         }
     }
 
@@ -1464,6 +1649,20 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
     wxPrintf( wxT(".\n") );
 */
 
+#ifndef __WXGTK20__
+    if (event_type == wxEVT_LEFT_DCLICK)
+    {
+        // GTK 1.2 crashes when intercepting double
+        // click events from both wxSpinButton and
+        // wxSpinCtrl
+        if (GTK_IS_SPIN_BUTTON(win->m_widget))
+        {
+            // Just disable this event for now.
+            return FALSE;
+        }
+    }
+#endif
+
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
@@ -1477,7 +1676,9 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
 // "button_release_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
+static gint gtk_window_button_release_callback( GtkWidget *widget,
+                                                GdkEventButton *gdk_event,
+                                                wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1490,21 +1691,25 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
 
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
-/*
-    printf( "OnButtonRelease from " );
-    if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
-        printf( win->GetClassInfo()->GetClassName() );
-    printf( ".\n" );
-*/
-
     wxEventType event_type = wxEVT_NULL;
 
     switch (gdk_event->button)
     {
-        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;
+        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:
+            // unknwon button, don't process
+            return FALSE;
     }
 
     wxMouseEvent event( event_type );
@@ -1515,6 +1720,20 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
     // same wxListBox hack as above
     win->FixUpMouseEvent(widget, event.m_x, event.m_y);
 
+    if ( event_type == wxEVT_RIGHT_UP )
+    {
+        // generate a "context menu" event: this is similar to wxEVT_RIGHT_UP
+        // except that:
+        //
+        // (a) it's a command event and so is propagated to the parent
+        // (b) under MSW it can be generated from kbd too
+        // (c) it uses screen coords (because of (a))
+        wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
+                                  win->GetId(),
+                                  win->ClientToScreen(event.GetPosition()));
+        (void)win->GetEventHandler()->ProcessEvent(evtCtx);
+    }
+
     if ( !g_captureWindow )
         win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
 
@@ -1570,6 +1789,10 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
     {
         // synthetize a mouse enter or leave event if needed
         GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL);
+        // This seems to be necessary and actually been added to
+        // GDK itself in version 2.0.X
+        gdk_flush();
+
         bool hasMouse = winUnderMouse == gdk_event->window;
         if ( hasMouse != g_captureWindowHasMouse )
         {
@@ -1597,6 +1820,62 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
     return FALSE;
 }
 
+#ifdef __WXGTK20__
+//-----------------------------------------------------------------------------
+// "mouse_wheel_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_wheel_callback (GtkWidget * widget,
+                                       GdkEventScroll * gdk_event,
+                                       wxWindowGTK * win)
+{
+    DEBUG_MAIN_THREAD
+
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    wxEventType event_type = wxEVT_NULL;
+    if (gdk_event->direction == GDK_SCROLL_UP)
+        event_type = wxEVT_MOUSEWHEEL;
+    else if (gdk_event->direction == GDK_SCROLL_DOWN)
+        event_type = wxEVT_MOUSEWHEEL;
+    else
+        return FALSE;
+    
+    wxMouseEvent event( event_type );
+    // Can't use InitMouse macro because scroll events don't have button
+    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_linesPerAction = 3;
+    if (gdk_event->direction == GDK_SCROLL_UP)
+        event.m_wheelRotation = 120;
+    else
+        event.m_wheelRotation = -120;
+
+    wxPoint pt = win->GetClientAreaOrigin();
+    event.m_x = (wxCoord)gdk_event->x - pt.x;
+    event.m_y = (wxCoord)gdk_event->y - pt.y;
+
+    event.SetEventObject( win );
+    event.SetId( win->GetId() );
+    event.SetTimestamp( gdk_event->time );
+    
+    if (win->GetEventHandler()->ProcessEvent( event ))
+    {
+        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "scroll_event" );
+        return TRUE;
+    }
+
+    return FALSE;
+}
+#endif
+
 //-----------------------------------------------------------------------------
 // "focus_in_event"
 //-----------------------------------------------------------------------------
@@ -1663,7 +1942,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
 #endif // wxUSE_CARET
 
     g_activeFrameLostFocus = FALSE;
-    
+
     wxWindowGTK *active = wxGetTopLevelParent(win);
     if ( active != g_activeFrame )
     {
@@ -1680,7 +1959,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
         wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId());
         event.SetEventObject(g_activeFrame);
         g_activeFrame->GetEventHandler()->ProcessEvent(event);
-        
+
         // Don't send focus events in addition to activate
         // if (win == g_activeFrame)
         //    return TRUE;
@@ -1793,6 +2072,9 @@ gint gtk_window_enter_callback( GtkWidget *widget,
     if (!win->m_hasVMT) return FALSE;
     if (g_blockEventsOnDrag) return FALSE;
 
+    // Event was emitted after a grab
+    if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
+
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
     int x = 0;
@@ -1830,6 +2112,9 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
     if (!win->m_hasVMT) return FALSE;
     if (g_blockEventsOnDrag) return FALSE;
 
+    // Event was emitted after an ungrab
+    if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
+
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
     wxMouseEvent event( wxEVT_LEAVE_WINDOW );
@@ -1885,7 +2170,9 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
 
     win->m_oldVerticalPos = adjust->value;
 
+#ifndef __WXGTK20__
     GtkScrolledWindow   *sw = GTK_SCROLLED_WINDOW(win->m_widget);
+#endif
     wxEventType         command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->vscrollbar));
 
     int value = (int)(adjust->value+0.5);
@@ -1914,7 +2201,9 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
     float diff = adjust->value - win->m_oldHorizontalPos;
     if (fabs(diff) < 0.2) return;
 
+#ifndef __WXGTK20__
     GtkScrolledWindow   *sw = GTK_SCROLLED_WINDOW(win->m_widget);
+#endif
     wxEventType         command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->hscrollbar));
 
     win->m_oldHorizontalPos = adjust->value;
@@ -2006,21 +2295,6 @@ wxWindow *wxWindowBase::FindFocus()
     return (wxWindow *)g_focusWindow;
 }
 
-//-----------------------------------------------------------------------------
-// "destroy" event
-//-----------------------------------------------------------------------------
-
-// VZ: Robert commented the code using out so it generates warnings: should
-//     be either fixed or removed completely
-#if 0
-
-static void gtk_window_destroy_callback( GtkWidget* widget, wxWindow *win )
-{
-    wxWindowDestroyEvent event(win);
-    win->GetEventHandler()->ProcessEvent(event);
-}
-
-#endif // 0
 
 //-----------------------------------------------------------------------------
 // "realize" from m_widget
@@ -2030,19 +2304,27 @@ static void gtk_window_destroy_callback( GtkWidget* widget, wxWindow *win )
    been realized, so we do this directly after realization. */
 
 static gint
-gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
+gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
     if (g_isIdle)
         wxapp_install_idle_handler();
-
-    if (win->m_delayedBackgroundColour)
+        
+    if (win->m_delayedBackgroundColour && !win->GetThemeEnabled())
         win->GtkSetBackgroundColour( win->GetBackgroundColour() );
 
-    if (win->m_delayedForegroundColour)
+    if (win->m_delayedForegroundColour && !win->GetThemeEnabled())
         win->GtkSetForegroundColour( win->GetForegroundColour() );
 
+#ifdef __WXGTK20__
+    if (win->m_imContext)
+    {
+        GtkPizza *pizza = GTK_PIZZA( m_widget );
+        gtk_im_context_set_client_window( (GtkIMContext*) win->m_imContext, pizza->bin_window );
+    }
+#endif
+
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
@@ -2257,9 +2539,6 @@ wxWindow *wxGetActiveWindow()
 
 void wxWindowGTK::Init()
 {
-    // common init
-    InitBase();
-
     // GTK specific
     m_widget = (GtkWidget *) NULL;
     m_wxwindow = (GtkWidget *) NULL;
@@ -2284,8 +2563,10 @@ void wxWindowGTK::Init()
 
     m_hAdjust = (GtkAdjustment*) NULL;
     m_vAdjust = (GtkAdjustment*) NULL;
-    m_oldHorizontalPos = 0.0;
+    m_oldHorizontalPos =
     m_oldVerticalPos = 0.0;
+    m_oldClientWidth =
+    m_oldClientHeight = 0;
 
     m_resizing = FALSE;
     m_widgetStyle = (GtkStyle*) NULL;
@@ -2302,10 +2583,15 @@ void wxWindowGTK::Init()
     m_delayedForegroundColour = FALSE;
     m_delayedBackgroundColour = FALSE;
 
+#ifdef __WXGTK20__
+    m_imContext = NULL;
+    m_x11Context = NULL;
+#else
 #ifdef HAVE_XIM
     m_ic = (GdkIC*) NULL;
     m_icattr = (GdkICAttr*) NULL;
 #endif
+#endif
 }
 
 wxWindowGTK::wxWindowGTK()
@@ -2340,9 +2626,9 @@ bool wxWindowGTK::Create( wxWindow *parent,
     }
 
     m_insertCallback = wxInsertChildInWindow;
-    
+
     // always needed for background clearing
-    m_delayedBackgroundColour = TRUE; 
+    m_delayedBackgroundColour = TRUE;
 
     m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
     GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
@@ -2426,6 +2712,17 @@ bool wxWindowGTK::Create( wxWindow *parent,
     gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
           (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
 
+#ifdef __WXGTK20__
+    // Create input method handler
+    m_imContext = (GtkIMMulticontext*) gtk_im_multicontext_new ();
+
+    // Cannot handle drawing preedited text yet
+    gtk_im_context_set_use_preedit( (GtkIMContext*) m_imContext, FALSE );
+
+    g_signal_connect (G_OBJECT (m_imContext), "commit",
+        G_CALLBACK (gtk_wxwindow_commit_cb), this);
+#endif
+
     gtk_widget_show( m_wxwindow );
 
     if (m_parent)
@@ -2442,6 +2739,8 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
 wxWindowGTK::~wxWindowGTK()
 {
+    SendDestroyEvent();
+
     if (g_focusWindow == this)
         g_focusWindow = NULL;
 
@@ -2459,9 +2758,6 @@ wxWindowGTK::~wxWindowGTK()
 
     DestroyChildren();
 
-    if (m_parent)
-        m_parent->RemoveChild( this );
-
 #ifdef HAVE_XIM
     if (m_ic)
         gdk_ic_destroy (m_ic);
@@ -2496,10 +2792,8 @@ bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const w
 {
     wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
 
-    // This turns -1 into 30 so that a minimal window is
-    // visible even although -1,-1 has been given as the
-    // size of the window. the same trick is used in other
-    // ports and should make debugging easier.
+    // Use either the given size, or the default if -1 is given.
+    // See wxWindowBase for these functions.
     m_width = WidthDefault(size.x) ;
     m_height = HeightDefault(size.y);
 
@@ -2543,13 +2837,24 @@ void wxWindowGTK::PostCreation()
             gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
                 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
 
-            if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
+            if (!HasFlag(wxFULL_REPAINT_ON_RESIZE))
             {
                 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
             }
 #else
-            gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ) );
+            // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
+#endif
+
+#ifdef __WXGTK20__
+        // Create input method handler
+        m_imContext = (GtkIMMulticontext*) gtk_im_multicontext_new ();
+
+        // Cannot handle drawing preedited text yet
+        gtk_im_context_set_use_preedit( (GtkIMContext*) m_imContext, FALSE );
+
+        g_signal_connect (G_OBJECT (m_imContext), "commit",
+            G_CALLBACK (gtk_wxwindow_commit_cb), this);
 #endif
         }
 
@@ -2600,7 +2905,7 @@ void wxWindowGTK::PostCreation()
                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
     }
 
-    if (!GTK_IS_COMBO(m_widget))
+    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
@@ -2608,7 +2913,8 @@ void wxWindowGTK::PostCreation()
         // 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 );
+                            GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback),
+                            (gpointer) this );
     }
 
     m_hasVMT = TRUE;
@@ -2631,16 +2937,16 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
     gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
 
+#ifdef __WXGTK20__
+    gtk_signal_connect( GTK_OBJECT(widget), "scroll_event",
+      GTK_SIGNAL_FUNC(gtk_window_wheel_callback), (gpointer)this );
+#endif
+
     gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
       GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
 
     gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
       GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
-      
-    // This keeps crashing on me. RR.
-    //
-    // gtk_signal_connect( GTK_OBJECT(widget), "destroy",
-    //  GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this );
 }
 
 bool wxWindowGTK::Destroy()
@@ -2671,9 +2977,9 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
 
     int currentX, currentY;
     GetPosition(&currentX, &currentY);
-    if (x == -1)
+    if (x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
         x = currentX;
-    if (y == -1)
+    if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
         y = currentY;
     AdjustForParentClientOrigin(x, y, sizeFlags);
 
@@ -2698,18 +3004,22 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
             m_x = x + pizza->xoffset;
             m_y = y + pizza->yoffset;
         }
-        if (width != -1) m_width = width;
-        if (height != -1) m_height = height;
 
-        if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
+        // calculate the best size if we should auto size the window
+        if ( (sizeFlags & wxSIZE_AUTO_WIDTH) ||
+                (sizeFlags & wxSIZE_AUTO_HEIGHT) )
         {
-             if (width == -1) m_width = 80;
+            const wxSize sizeBest = GetBestSize();
+            if ( sizeFlags & wxSIZE_AUTO_WIDTH )
+                width = sizeBest.x;
+            if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
+                height = sizeBest.y;
         }
 
-        if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
-        {
-             if (height == -1) m_height = 26;
-        }
+        if (width != -1)
+            m_width = width;
+        if (height != -1)
+            m_height = height;
 
         int minWidth = GetMinWidth(),
             minHeight = GetMinHeight(),
@@ -2795,7 +3105,7 @@ void wxWindowGTK::OnInternalIdle()
         }
         g_activeFrameLostFocus = FALSE;
     }
-    
+
     wxCursor cursor = m_cursor;
     if (g_globalCursor.Ok()) cursor = g_globalCursor;
 
@@ -2830,7 +3140,8 @@ void wxWindowGTK::OnInternalIdle()
         }
     }
 
-    UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
@@ -3066,6 +3377,11 @@ bool wxWindowGTK::Show( bool show )
     else
         gtk_widget_hide( m_widget );
 
+    wxShowEvent eventShow(GetId(), show);
+    eventShow.m_eventObject = this;
+
+    GetEventHandler()->ProcessEvent(eventShow);
+
     return TRUE;
 }
 
@@ -3076,7 +3392,7 @@ static void wxWindowNotifyEnable(wxWindowGTK* win, bool 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();
+    for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
           node;
           node = node->GetNext() )
     {
@@ -3111,9 +3427,31 @@ int wxWindowGTK::GetCharHeight() const
 
     wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
 
+#ifdef __WXGTK20__
+    PangoContext *context = NULL;
+    if (m_widget)
+        context = gtk_widget_get_pango_context( m_widget );
+
+    if (!context)
+        return 0;
+
+    PangoFontDescription *desc = m_font.GetNativeFontInfo()->description;
+    PangoLayout *layout = pango_layout_new(context);
+    pango_layout_set_font_description(layout, desc);
+    pango_layout_set_text(layout, "H", 1);
+    PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+
+    PangoRectangle rect;
+    pango_layout_line_get_extents(line, NULL, &rect);
+
+    g_object_unref( G_OBJECT( layout ) );
+
+    return (int) (rect.height / PANGO_SCALE);
+#else
     GdkFont *font = m_font.GetInternalFont( 1.0 );
 
     return font->ascent + font->descent;
+#endif
 }
 
 int wxWindowGTK::GetCharWidth() const
@@ -3122,9 +3460,31 @@ int wxWindowGTK::GetCharWidth() const
 
     wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
 
+#ifdef __WXGTK20__
+    PangoContext *context = NULL;
+    if (m_widget)
+        context = gtk_widget_get_pango_context( m_widget );
+
+    if (!context)
+        return 0;
+
+    PangoFontDescription *desc = m_font.GetNativeFontInfo()->description;
+    PangoLayout *layout = pango_layout_new(context);
+    pango_layout_set_font_description(layout, desc);
+    pango_layout_set_text(layout, "g", 1);
+    PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+
+    PangoRectangle rect;
+    pango_layout_line_get_extents(line, NULL, &rect);
+
+    g_object_unref( G_OBJECT( layout ) );
+
+    return (int) (rect.width / PANGO_SCALE);
+#else
     GdkFont *font = m_font.GetInternalFont( 1.0 );
 
-    return gdk_string_width( font, "H" );
+    return gdk_string_width( font, "g" );
+#endif
 }
 
 void wxWindowGTK::GetTextExtent( const wxString& string,
@@ -3139,11 +3499,60 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
 
     wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
+    if (string.IsEmpty())
+    {
+        if (x) (*x) = 0;
+        if (y) (*y) = 0;
+        return;
+    }
+
+#ifdef __WXGTK20__
+    PangoContext *context = NULL;
+    if (m_widget)
+        context = gtk_widget_get_pango_context( m_widget );
+
+    if (!context)
+    {
+        if (x) (*x) = 0;
+        if (y) (*y) = 0;
+        return;
+    }
+
+    PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description;
+    PangoLayout *layout = pango_layout_new(context);
+    pango_layout_set_font_description(layout, desc);
+    {
+#if wxUSE_UNICODE
+        const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
+        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+#else
+        const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
+        const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
+        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+#endif
+    }
+    PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+
+    PangoRectangle rect;
+    pango_layout_line_get_extents(line, NULL, &rect);
+
+    if (x) (*x) = (wxCoord) (rect.width / PANGO_SCALE);
+    if (y) (*y) = (wxCoord) (rect.height / PANGO_SCALE);
+    if (descent)
+    {
+        // Do something about metrics here
+        (*descent) = 0;
+    }
+    if (externalLeading) (*externalLeading) = 0;  // ??
+
+    g_object_unref( G_OBJECT( layout ) );
+#else
     GdkFont *font = fontToUse.GetInternalFont( 1.0 );
     if (x) (*x) = gdk_string_width( font, wxGTK_CONV( string ) );
     if (y) (*y) = font->ascent + font->descent;
     if (descent) (*descent) = font->descent;
     if (externalLeading) (*externalLeading) = 0;  // ??
+#endif
 }
 
 void wxWindowGTK::SetFocus()
@@ -3312,11 +3721,23 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
     if (!m_widget) return;
     if (!m_widget->window) return;
-    
+
 #ifndef __WXGTK20__
     if (g_isIdle)
         wxapp_install_idle_handler();
-        
+
+    wxRect myRect(0,0,0,0);
+    if (m_wxwindow && rect)
+    {
+        myRect.SetSize(wxSize( m_wxwindow->allocation.width,
+                               m_wxwindow->allocation.height));
+        myRect.Intersect(*rect);
+        if (!myRect.width || !myRect.height)
+            // nothing to do, rectangle is empty
+            return;
+        rect = &myRect;
+    }
+
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
     {
         if (rect)
@@ -3392,28 +3813,31 @@ void wxWindowGTK::GtkUpdate()
 #ifdef __WXGTK20__
     if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
         gdk_window_process_updates( GTK_PIZZA(m_wxwindow)->bin_window, FALSE );
-#endif
-
+#else
     if (!m_updateRegion.IsEmpty())
         GtkSendPaintEvents();
+#endif
 }
 
 void wxWindowGTK::GtkSendPaintEvents()
 {
     if (!m_wxwindow)
     {
+#ifndef __WXGTK20__
         m_clearRegion.Clear();
+#endif
         m_updateRegion.Clear();
         return;
     }
 
-    // widget to draw on
-    GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
-            
     // Clip to paint region in wxClientDC
     m_clipPaintRegion = TRUE;
 
-#ifndef __WXGTK20__    
+#ifndef __WXGTK20__
+    // widget to draw on
+    GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
+
+    // later for GTK 2.0, too.
     if (GetThemeEnabled())
     {
         // find ancestor from which to steal background
@@ -3422,7 +3846,7 @@ void wxWindowGTK::GtkSendPaintEvents()
             parent = parent->GetParent();
         if (!parent)
             parent = (wxWindow*)this;
-    
+
         wxRegionIterator upd( m_updateRegion );
         while (upd)
         {
@@ -3431,7 +3855,7 @@ void wxWindowGTK::GtkSendPaintEvents()
             rect.y = upd.GetY();
             rect.width = upd.GetWidth();
             rect.height = upd.GetHeight();
-                    
+
             gtk_paint_flat_box( parent->m_widget->style,
                         pizza->bin_window,
                         GTK_STATE_NORMAL,
@@ -3440,15 +3864,25 @@ void wxWindowGTK::GtkSendPaintEvents()
                         parent->m_widget,
                         (char *)"base",
                         0, 0, -1, -1 );
-                        
+
             upd ++;
         }
     }
     else
 #endif
-#ifdef __WXGTK20__    
-    if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2
-#endif
+
+#ifdef __WXGTK20__
+    {
+        wxWindowDC dc( (wxWindow*)this );
+        dc.SetClippingRegion( m_updateRegion );
+
+        wxEraseEvent erase_event( GetId(), &dc );
+        erase_event.SetEventObject( this );
+
+        GetEventHandler()->ProcessEvent(erase_event);
+    }
+#else
+    // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2
     {
         wxWindowDC dc( (wxWindow*)this );
         if (m_clearRegion.IsEmpty())
@@ -3461,7 +3895,6 @@ void wxWindowGTK::GtkSendPaintEvents()
 
         if (!GetEventHandler()->ProcessEvent(erase_event))
         {
-#ifndef __WXGTK20__    
             if (!g_eraseGC)
             {
                 g_eraseGC = gdk_gc_new( pizza->bin_window );
@@ -3476,10 +3909,10 @@ void wxWindowGTK::GtkSendPaintEvents()
                                     upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
                 upd ++;
             }
-#endif
         }
         m_clearRegion.Clear();
     }
+#endif
 
     wxNcPaintEvent nc_paint_event( GetId() );
     nc_paint_event.SetEventObject( this );
@@ -3502,7 +3935,7 @@ void wxWindowGTK::GtkSendPaintEvents()
     {
         GtkPizzaChild *child = (GtkPizzaChild*) children->data;
         children = children->next;
-        
+
         if (GTK_WIDGET_NO_WINDOW (child->widget) &&
             GTK_WIDGET_DRAWABLE (child->widget))
         {
@@ -3538,19 +3971,21 @@ void wxWindowGTK::GtkSendPaintEvents()
     m_updateRegion.Clear();
 }
 
-void wxWindowGTK::Clear()
+void wxWindowGTK::ClearBackground()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
+#ifndef __WXGTK20__
     if (m_wxwindow && m_wxwindow->window)
     {
         m_clearRegion.Clear();
         wxSize size( GetClientSize() );
         m_clearRegion.Union( 0,0,size.x,size.y );
-        
+
         // Better do this in idle?
         GtkUpdate();
     }
+#endif
 }
 
 #if wxUSE_TOOLTIPS
@@ -3564,7 +3999,8 @@ void wxWindowGTK::DoSetToolTip( wxToolTip *tip )
 
 void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
 {
-    gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
+    wxString tmp( tip );
+    gtk_tooltips_set_tip( tips, GetConnectWidget(), wxGTK_CONV(tmp), (gchar*) NULL );
 }
 #endif // wxUSE_TOOLTIPS
 
@@ -3577,10 +4013,10 @@ void wxWindowGTK::GtkSetBackgroundColour( const wxColour &colour )
         window = GetConnectWidget()->window;
 
     wxASSERT( window );
-    
+
     // We need the pixel value e.g. for background clearing.
     m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
-    
+
     if (m_wxwindow)
     {
         // wxMSW doesn't clear the window here, either.
@@ -3664,6 +4100,21 @@ bool wxWindowGTK::SetForegroundColour( const wxColour &colour )
     return TRUE;
 }
 
+#ifdef __WXGTK20__
+PangoContext *wxWindowGTK::GtkGetPangoDefaultContext()
+{
+    return gtk_widget_get_pango_context( m_widget );
+}
+
+PangoContext *wxWindowGTK::GtkGetPangoX11Context()
+{
+    if (!m_x11Context)
+        m_x11Context = pango_x_get_context( gdk_display );
+
+    return m_x11Context;
+}
+#endif
+
 GtkStyle *wxWindowGTK::GetWidgetStyle()
 {
     if (m_widgetStyle)
@@ -3716,7 +4167,13 @@ void wxWindowGTK::SetWidgetStyle()
 
     if (m_font != wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ))
     {
-        SET_STYLE_FONT(style, m_font.GetInternalFont( 1.0 ));
+#ifdef __WXGTK20__
+        pango_font_description_free( style->font_desc );
+        style->font_desc = pango_font_description_copy( m_font.GetNativeFontInfo()->description );
+#else
+        gdk_font_unref( style->font );
+        style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
+#endif
     }
 
     if (m_foregroundColour.Ok())
@@ -3803,7 +4260,7 @@ void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting  )
 static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
 {
     menu->SetInvokingWindow( win );
-    wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+    wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
     while (node)
     {
         wxMenuItem *menuitem = node->GetData();
@@ -3872,13 +4329,16 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
                   wxPopupMenuPositionCallback,  // function to position it
                   NULL,                         // client data
                   0,                            // button used to activate it
+#ifdef __WXGTK20__
+                  gtk_get_current_event_time()
+#else
                   gs_timeLastClick              // the time of activation
+#endif
                 );
 
     while (is_waiting)
     {
-        while (gtk_events_pending())
-            gtk_main_iteration();
+        gtk_main_iteration();
     }
 
     return TRUE;
@@ -3922,9 +4382,7 @@ bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window )
 
 bool wxWindowGTK::SetFont( const wxFont &font )
 {
-    wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
-
-    if (!wxWindowBase::SetFont(font))
+    if (!wxWindowBase::SetFont(font) || !m_widget)
     {
         return FALSE;
     }
@@ -4161,7 +4619,7 @@ 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") );
-    
+
     // No scrolling requested.
     if ((dx == 0) && (dy == 0)) return;
 
@@ -4185,20 +4643,13 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
         GetClientSize( &cw, &ch );
         m_clearRegion.Intersect( 0, 0, cw, ch );
     }
+#endif
+
     m_clipPaintRegion = TRUE;
 
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
 
     m_clipPaintRegion = FALSE;
-#else
-
-    gdk_window_scroll( GTK_PIZZA(m_wxwindow)->bin_window, dx, dy );
-
-    GTK_PIZZA(m_wxwindow)->xoffset += dx;
-    GTK_PIZZA(m_wxwindow)->yoffset += dy;
-
-#endif
-
 }
 
 
@@ -4225,10 +4676,8 @@ wxPoint wxGetMousePosition()
 
     int x, y;
     GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
-    if (!windowAtPtr)
-      return wxPoint(-999, -999);
 
-    Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
+    Display *display = windowAtPtr ? GDK_WINDOW_XDISPLAY(windowAtPtr) : GDK_DISPLAY();
     Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
     Window rootReturn, childReturn;
     int rootX, rootY, winX, winY;