]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
wxGTK: Implemented wxTLW::RequestUserAttention()
[wxWidgets.git] / src / gtk / window.cpp
index 41a21c2a140222215383a626930294e8710ba9b8..536777c8f04b29d99241dba2dde40f7bacfb46ed 100644 (file)
@@ -28,6 +28,7 @@
 #include "wx/dialog.h"
 #include "wx/msgdlg.h"
 #include "wx/module.h"
+#include "wx/combobox.h"
 
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
@@ -56,7 +57,7 @@
     #include "wx/thread.h"
 #endif
 
-#include <math.h>
+#include "wx/math.h"
 #include <ctype.h>
 
 #include "wx/gtk/private.h"
@@ -228,14 +229,14 @@ static GdkGC *g_eraseGC = NULL;
 // mouse capture state: the window which has it and if the mouse is currently
 // inside it
 static wxWindowGTK  *g_captureWindow = (wxWindowGTK*) NULL;
-static bool g_captureWindowHasMouse = FALSE;
+static bool g_captureWindowHasMouse = false;
 
-/* extern */ wxWindowGTK  *g_focusWindow = (wxWindowGTK*) NULL;
+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;
+wxWindowGTK *g_focusWindowLast = (wxWindowGTK*) NULL;
 
 // If a window get the focus set but has not been realized
 // yet, defer setting the focus to idle time.
@@ -243,7 +244,7 @@ wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL;
 
 // 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; 
+static guint32 gs_timeLastClick = 0;
 
 extern bool g_mainThreadLocked;
 
@@ -378,7 +379,7 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
             dh += hscroll_req.height;
             dh += scroll_class->scrollbar_spacing;
         }
-}
+    }
 
     int dx = 0;
     int dy = 0;
@@ -428,7 +429,8 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
 // "expose_event" of m_widget
 //-----------------------------------------------------------------------------
 
-gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win )
+extern "C" {
+static gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win )
 {
     if (gdk_event->count > 0) return FALSE;
 
@@ -441,6 +443,7 @@ gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_even
 #endif
     return TRUE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "draw" of m_widget
@@ -448,10 +451,12 @@ gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_even
 
 #ifndef __WXGTK20__
 
+extern "C" {
 static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindowGTK *win )
 {
     draw_frame( widget, win );
 }
+}
 
 #endif // GTK+ < 2.0
 
@@ -459,8 +464,8 @@ static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNU
 // "size_request" of m_widget
 //-----------------------------------------------------------------------------
 
-// make it extern because wxStatitText needs to disconnect this one
-extern "C"
+// make it extern because wxStaticText needs to disconnect this one
+extern "C" {
 void wxgtk_window_size_request_callback(GtkWidget *widget,
                                         GtkRequisition *requisition,
                                         wxWindow *win)
@@ -475,11 +480,42 @@ void wxgtk_window_size_request_callback(GtkWidget *widget,
     requisition->height = h;
     requisition->width = w;
 }
+}
+
+extern "C" {
+static
+void wxgtk_combo_size_request_callback(GtkWidget *widget,
+                                       GtkRequisition *requisition,
+                                       wxComboBox *win)
+{
+    // This callback is actually hooked into the text entry
+    // of the combo box, not the GtkHBox.
+
+    int w, h;
+    win->GetSize( &w, &h );
+    if (w < 2)
+        w = 2;
+    if (h < 2)
+        h = 2;
+
+    GtkCombo *gcombo = GTK_COMBO(win->m_widget);
+
+    GtkRequisition entry_req;
+    entry_req.width = 2;
+    entry_req.height = 2;
+    (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo->button) )->size_request )
+        (gcombo->button, &entry_req );
+
+    requisition->width = w - entry_req.width;
+    requisition->height = entry_req.height;
+}
+}
 
 //-----------------------------------------------------------------------------
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static int gtk_window_expose_callback( GtkWidget *widget,
                                        GdkEventExpose *gdk_event,
                                        wxWindow *win )
@@ -508,7 +544,7 @@ 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,
@@ -549,17 +585,22 @@ static int gtk_window_expose_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
+#ifndef __WXGTK20__
+
 // 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.
 
+extern "C" {
+static
 gint gtk_window_event_event_callback( GtkWidget *widget,
                                       GdkEventExpose *event,
                                       wxWindow *win )
@@ -572,6 +613,9 @@ gint gtk_window_event_event_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
+
+#endif // !GTK+ 2
 
 //-----------------------------------------------------------------------------
 // "draw" of m_wxwindow
@@ -582,6 +626,7 @@ gint gtk_window_event_event_callback( GtkWidget *widget,
 // This callback is a complete replacement of the gtk_pizza_draw() function,
 // which is disabled.
 
+extern "C" {
 static void gtk_window_draw_callback( GtkWidget *widget,
                                       GdkRectangle *rect,
                                       wxWindow *win )
@@ -657,6 +702,7 @@ static void gtk_window_draw_callback( GtkWidget *widget,
     }
 #endif
 }
+}
 
 #endif
 
@@ -960,6 +1006,7 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
         gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
 
     event.SetTimestamp( gdk_event->time );
+    event.SetId(win->GetId());
     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0;
     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
@@ -967,6 +1014,11 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
     event.m_scanCode = gdk_event->keyval;
     event.m_rawCode = (wxUint32) gdk_event->keyval;
     event.m_rawFlags = 0;
+#if wxUSE_UNICODE
+    event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval);
+#endif
+    wxGetMousePosition( &x, &y );
+    win->ScreenToClient( &x, &y );
     event.m_x = x;
     event.m_y = y;
     event.SetEventObject( win );
@@ -996,7 +1048,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
                                                     : _T("press"),
                keysym);
 
-    long key_code = wxTranslateKeySymToWXKey(keysym, FALSE /* !isChar */);
+    long key_code = wxTranslateKeySymToWXKey(keysym, false /* !isChar */);
 
     if ( !key_code )
     {
@@ -1065,14 +1117,14 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
 
     // sending unknown key events doesn't really make sense
     if ( !key_code )
-        return FALSE;
+        return false;
 
     // now fill all the other fields
     wxFillOtherKeyEventFields(event, win, gdk_event);
-    
+
     event.m_keyCode = key_code;
 
-    return TRUE;
+    return true;
 }
 
 
@@ -1094,6 +1146,7 @@ struct wxGtkIMData
 };
 #endif
 
+extern "C" {
 static gint gtk_window_key_press_callback( GtkWidget *widget,
                                            GdkEventKey *gdk_event,
                                            wxWindow *win )
@@ -1107,48 +1160,113 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         return FALSE;
     if (g_blockEventsOnDrag)
         return FALSE;
-    
-#ifdef __WXGTK20__
-    // We have to pass key press events through GTK+'s Input Method context
-    // object in order to get correct characters. By doing so, we loose the
-    // ability to let other GTK+'s handlers (namely, widgets' default signal
-    // handlers) handle the signal by returning false from this callback.
-    // Because GTK+ sends the events to parent widgets as well, we can't
-    // afford loosing it, otherwise native widgets inserted into wxPanel
-    // would break in subtle ways (e.g. spacebar would no longer toggle
-    // wxCheckButton's state). Therefore, we only pass the event to IM if it
-    // originated in this window's widget, which we detect by checking if we've
-    // seen the same event before (no events from children are lost this way,
-    // because gtk_window_key_press_callback is installed for native controls
-    // as well and the wxKeyEvent it creates propagates upwards).
-    static GdkEventKey s_lastEvent;
-    
-    bool useIM = (win->m_imData != NULL) &&
-                 memcmp(gdk_event, &s_lastEvent, sizeof(GdkEventKey)) != 0;
-    
-    s_lastEvent = *gdk_event;
-#endif
-    
+
+
     wxKeyEvent event( wxEVT_KEY_DOWN );
-    if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
+    bool ret = false;
+    bool return_after_IM = false;
+
+    if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
+    {
+        // Emit KEY_DOWN event
+        ret = win->GetEventHandler()->ProcessEvent( event );
+    }
+    else
     {
-        // unknown key pressed, ignore (the event would be useless anyhow)
+        // Return after IM processing as we cannot do
+        // anything with it anyhow.
+        return_after_IM = true;
+    }
+
 #ifdef __WXGTK20__
-        if ( useIM )
+    // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw):
+    // When we get a key_press event here, it could be originate
+    // from the current widget or its child widgets.  However, only the widget
+    // with the INPUT FOCUS can generate the INITIAL key_press event.  That is,
+    // if the CURRENT widget doesn't have the FOCUS at all, this event definitely
+    // originated from its child widgets and shouldn't be passed to IM context.
+    // In fact, what a GTK+ IM should do is filtering keyEvents and convert them
+    // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS.  Besides, when current
+    // widgets has both IM context and input focus, the event should be filtered
+    // by gtk_im_context_filter_keypress().
+    // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns.
+    if ((!ret) && (win->m_imData != NULL) && ( wxWindow::FindFocus() == win ))
+    {
+        // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
+        // docs, if IM filter returns true, no further processing should be done.
+        // we should send the key_down event anyway.
+        bool intercepted_by_IM = gtk_im_context_filter_keypress(win->m_imData->context, gdk_event);
+        win->m_imData->lastKeyEvent = NULL;
+        if (intercepted_by_IM)
         {
-            // it may be useful for the input method, though:
-            win->m_imData->lastKeyEvent = gdk_event;
-            bool ret = gtk_im_context_filter_keypress(win->m_imData->context,
-                                                      gdk_event);
-            win->m_imData->lastKeyEvent = NULL;
-            return ret;
+            wxLogTrace(TRACE_KEYS, _T("Key event intercepted by IM"));
+            return true;
         }
+    }
 #endif
-        return FALSE;
+    if (return_after_IM)
+        return false;
+
+#ifndef __WXGTK20__
+    // This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done
+    // in the "commit" handler.
+
+    // 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw).
+    // In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose
+    // keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are
+    // composed of more than one character, which means gdk_event->length will always
+    // greater than one. When gtk_event->length == 1, this may be an ASCII character
+    // and can be translated by wx.  However, when MBCS characters are sent by IM,
+    // gdk_event->length will >= 2. So neither should we pass it to accelerator table,
+    // nor should we pass it to controls. The following explanation was excerpted
+    // from GDK documentation.
+    // gint length : the length of string.
+    // gchar *string : a null-terminated multi-byte string containing the composed
+    // characters resulting from the key press. When text is being input, in a GtkEntry
+    // for example, it is these characters which should be added to the input buffer.
+    // When using Input Methods to support internationalized text input, the composed
+    // characters appear here after the pre-editing has been completed.
+
+    if ( (!ret) && (gdk_event->length > 1) ) // If this event contains a pre-edited string from IM.
+    {
+        // We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN.
+        #if wxUSE_UNICODE   // GTK+ 1.2 is not UTF-8 based.
+            const wxWCharBuffer string = wxConvLocal.cMB2WC( gdk_event->string );
+            if( !string )
+                return false;
+        #else
+            const char* string = gdk_event->string;
+        #endif
+
+        // Implement OnCharHook by checking ancesteror top level windows
+        wxWindow *parent = win;
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+
+        for( const wxChar* pstr = string; *pstr; pstr++ )
+        {
+        #if wxUSE_UNICODE
+            event.m_uniChar = *pstr;
+            // Backward compatible for ISO-8859-1
+            event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0;
+        #else
+            event.m_keyCode = *pstr;
+        #endif
+            if (parent)
+            {
+                event.SetEventType( wxEVT_CHAR_HOOK );
+                ret = parent->GetEventHandler()->ProcessEvent( event );
+            }
+            if (!ret)
+            {
+                event.SetEventType(wxEVT_CHAR);
+                win->GetEventHandler()->ProcessEvent( event );
+            }
+        }
+        return true;
     }
 
-    // Emit KEY_DOWN event
-    bool ret = win->GetEventHandler()->ProcessEvent( event );
+#endif  // #ifndef  __WXGTK20__
 
 #if wxUSE_ACCEL
     if (!ret)
@@ -1174,41 +1292,22 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     // will only be sent if it is not in an accelerator table.
     if (!ret)
     {
-#ifdef __WXGTK20__
-        if (useIM)
-        {
-            // 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.
-            win->m_imData->lastKeyEvent = gdk_event;
-            if ( gtk_im_context_filter_keypress(win->m_imData->context,
-                                                gdk_event) )
-            {
-                win->m_imData->lastKeyEvent = NULL;
-                wxLogTrace(TRACE_KEYS, _T("Key event intercepted by IM"));
-                return TRUE;
-            }
-            else
-                win->m_imData->lastKeyEvent = NULL;
-        }
-#endif
-
         long key_code;
         KeySym keysym = gdk_event->keyval;
         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
-        key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
+        key_code = wxTranslateKeySymToWXKey(keysym, true /* isChar */);
         if ( !key_code )
         {
-            if ( gdk_event->length == 1 )
-            {
-                key_code = (unsigned char)gdk_event->string[0];
-            }
-            else if ( wxIsAsciiKeysym(keysym) )
+            if ( wxIsAsciiKeysym(keysym) )
             {
                 // ASCII key
                 key_code = (unsigned char)keysym;
             }
+            // gdk_event->string is actually deprecated
+            else if ( gdk_event->length == 1 )
+            {
+                key_code = (unsigned char)gdk_event->string[0];
+            }
         }
 
         if ( key_code )
@@ -1235,6 +1334,10 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         }
     }
 
+
+
+
+
     // win is a control: tab can be propagated up
     if ( !ret &&
          ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
@@ -1304,8 +1407,10 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
 
 #ifdef __WXGTK20__
+extern "C" {
 static void gtk_wxwindow_commit_cb (GtkIMContext *context,
                            const gchar  *str,
                            wxWindow     *window)
@@ -1340,7 +1445,7 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
     {
 #if wxUSE_UNICODE
         event.m_uniChar = *pstr;
-        // Backward compatible for ISO-8859
+        // Backward compatible for ISO-8859-1
         event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0;
         wxLogTrace(TRACE_KEYS, _T("IM sent character '%c'"), event.m_uniChar);
 #else
@@ -1359,6 +1464,7 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
         }
     }
 }
+}
 #endif
 
 
@@ -1366,6 +1472,7 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
 // "key_release_event" from any window
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_key_release_callback( GtkWidget *widget,
                                              GdkEventKey *gdk_event,
                                              wxWindowGTK *win )
@@ -1394,6 +1501,7 @@ static gint gtk_window_key_release_callback( GtkWidget *widget,
     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
     return TRUE;
 }
+}
 
 // ============================================================================
 // the mouse events
@@ -1537,6 +1645,7 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
 // "button_press_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_button_press_callback( GtkWidget *widget,
                                               GdkEventButton *gdk_event,
                                               wxWindowGTK *win )
@@ -1595,6 +1704,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
     // GdkDisplay is a GTK+ 2.2.0 thing
 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0)
     if ( gdk_event->type == GDK_2BUTTON_PRESS &&
+            !gtk_check_version(2,2,0) &&
             gdk_event->button >= 1 && gdk_event->button <= 3 )
     {
         // Reset GDK internal timestamp variables in order to disable GDK
@@ -1688,21 +1798,6 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
     // a chance to correct this
     win->FixUpMouseEvent(widget, event.m_x, event.m_y);
 
-    if ( event_type == wxEVT_RIGHT_DOWN )
-    {
-        // generate a "context menu" event: this is similar to right mouse
-        // click under many GUIs except that it is generated differently
-        // (right up under MSW, ctrl-click under Mac, right down here) and
-        //
-        // (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);
-    }
-
     // find the correct window to send the event too: it may be a different one
     // from the one which got it at GTK+ level because some control don't have
     // their own X window and thus cannot get any events.
@@ -1731,13 +1826,32 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
         return TRUE;
     }
 
+    if (event_type == wxEVT_RIGHT_DOWN)
+    {
+        // generate a "context menu" event: this is similar to right mouse
+        // click under many GUIs except that it is generated differently
+        // (right up under MSW, ctrl-click under Mac, right down here) and
+        //
+        // (a) it's a command event and so is propagated to the parent
+        // (b) under some ports 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()));
+        evtCtx.SetEventObject(win);
+        return win->GetEventHandler()->ProcessEvent(evtCtx);
+    }
+
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "button_release_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_button_release_callback( GtkWidget *widget,
                                                 GdkEventButton *gdk_event,
                                                 wxWindowGTK *win )
@@ -1793,11 +1907,13 @@ static gint gtk_window_button_release_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "motion_notify_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_motion_notify_callback( GtkWidget *widget,
                                                GdkEventMotion *gdk_event,
                                                wxWindowGTK *win )
@@ -1867,15 +1983,17 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
 
 #ifdef __WXGTK20__
 //-----------------------------------------------------------------------------
 // "mouse_wheel_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_wheel_callback (GtkWidget * widget,
-                                       GdkEventScroll * gdk_event,
-                                       wxWindowGTK * win)
+                                       GdkEventScroll * gdk_event,
+                                       wxWindowGTK * win)
 {
     DEBUG_MAIN_THREAD
 
@@ -1889,7 +2007,7 @@ static gint gtk_window_wheel_callback (GtkWidget * widget,
         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 );
@@ -1914,7 +2032,7 @@ static gint gtk_window_wheel_callback (GtkWidget * widget,
     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" );
@@ -1923,7 +2041,23 @@ static gint gtk_window_wheel_callback (GtkWidget * widget,
 
     return FALSE;
 }
-#endif
+}
+
+//-----------------------------------------------------------------------------
+// "popup-menu"
+//-----------------------------------------------------------------------------
+extern "C" {
+static gboolean wxgtk_window_popup_menu_callback(GtkWidget*, wxWindowGTK* win)
+{
+    wxContextMenuEvent event(
+        wxEVT_CONTEXT_MENU,
+        win->GetId(),
+        wxPoint(-1, -1));
+    event.SetEventObject(win);
+    return win->GetEventHandler()->ProcessEvent(event);
+}
+}
+#endif // __WXGTK20__
 
 //-----------------------------------------------------------------------------
 // "focus_in_event"
@@ -1944,12 +2078,13 @@ static bool DoSendFocusEvents(wxWindow *win)
     return win->GetEventHandler()->ProcessEvent(eventFocus);
 }
 
+extern "C" {
 static gint gtk_window_focus_in_callback( GtkWidget *widget,
                                           GdkEvent *WXUNUSED(event),
                                           wxWindow *win )
 {
     DEBUG_MAIN_THREAD
-    
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1982,8 +2117,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
     if ( !win->m_hasFocus )
     {
         // not yet, notify it
-        win->m_hasFocus = TRUE;
-        
+        win->m_hasFocus = true;
+
         if ( DoSendFocusEvents(win) )
         {
            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
@@ -1993,11 +2128,13 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "focus_out_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
@@ -2038,7 +2175,7 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
     // have focus already
     if ( win->m_hasFocus )
     {
-        win->m_hasFocus = FALSE;
+        win->m_hasFocus = false;
 
         wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
         event.SetEventObject( win );
@@ -2052,11 +2189,13 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "enter_notify_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static
 gint gtk_window_enter_callback( GtkWidget *widget,
                                 GdkEventCrossing *gdk_event,
@@ -2095,11 +2234,13 @@ gint gtk_window_enter_callback( GtkWidget *widget,
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "leave_notify_event"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
@@ -2145,11 +2286,13 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "value_changed" from m_vAdjust
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
                                          SCROLLBAR_CBACK_ARG
                                          wxWindowGTK *win )
@@ -2179,11 +2322,13 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
 }
+}
 
 //-----------------------------------------------------------------------------
 // "value_changed" from m_hAdjust
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
                                          SCROLLBAR_CBACK_ARG
                                          wxWindowGTK *win )
@@ -2212,11 +2357,13 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
 }
+}
 
 //-----------------------------------------------------------------------------
 // "button_press_event" from scrollbar
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
                                                  GdkEventButton *gdk_event,
                                                  wxWindowGTK *win)
@@ -2227,7 +2374,7 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
         wxapp_install_idle_handler();
 
 
-    g_blockEventsOnScroll = TRUE;
+    g_blockEventsOnScroll = true;
 
     // FIXME: there is no 'slider' field in GTK+ 2.0 any more
 #ifndef __WXGTK20__
@@ -2236,11 +2383,13 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "button_release_event" from scrollbar
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
                                                    GdkEventButton *WXUNUSED(gdk_event),
                                                    wxWindowGTK *win)
@@ -2252,7 +2401,7 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
 //
 //    if (gdk_event->window != widget->slider) return FALSE;
 
-    g_blockEventsOnScroll = FALSE;
+    g_blockEventsOnScroll = false;
 
     if (win->m_isScrolling)
     {
@@ -2277,10 +2426,11 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
         win->GetEventHandler()->ProcessEvent( event );
     }
 
-    win->m_isScrolling = FALSE;
+    win->m_isScrolling = false;
 
     return FALSE;
 }
+}
 
 // ----------------------------------------------------------------------------
 // this wxWindowBase function is implemented here (in platform-specific file)
@@ -2293,7 +2443,6 @@ wxWindow *wxWindowBase::DoFindFocus()
     return (wxWindow *)g_focusWindow;
 }
 
-
 //-----------------------------------------------------------------------------
 // "realize" from m_widget
 //-----------------------------------------------------------------------------
@@ -2301,6 +2450,7 @@ wxWindow *wxWindowBase::DoFindFocus()
 /* We cannot set colours and fonts before the widget has
    been realized, so we do this directly after realization. */
 
+extern "C" {
 static gint
 gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 {
@@ -2308,7 +2458,7 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 
     if (g_isIdle)
         wxapp_install_idle_handler();
-        
+
 #ifdef __WXGTK20__
     if (win->m_imData)
     {
@@ -2324,11 +2474,13 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // "size_allocate"
 //-----------------------------------------------------------------------------
 
+extern "C" {
 static
 void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
                                GtkAllocation *WXUNUSED(alloc),
@@ -2355,6 +2507,7 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
         win->GetEventHandler()->ProcessEvent( event );
     }
 }
+}
 
 
 #ifdef HAVE_XIM
@@ -2365,6 +2518,7 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
 
 /* Resize XIM window */
 
+extern "C" {
 static
 void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
                                  GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
@@ -2388,6 +2542,7 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
     }
 #endif // HAVE_XIM
 }
+}
 
 //-----------------------------------------------------------------------------
 // "realize" from m_wxwindow
@@ -2395,6 +2550,7 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
 
 /* Initialize XIM support */
 
+extern "C" {
 static gint
 gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
                                 wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
@@ -2481,6 +2637,7 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
 
     return FALSE;
 }
+}
 
 //-----------------------------------------------------------------------------
 // InsertChild for wxWindowGTK.
@@ -2543,16 +2700,16 @@ void wxWindowGTK::Init()
     m_width = 0;
     m_height = 0;
 
-    m_sizeSet = FALSE;
-    m_hasVMT = FALSE;
-    m_needParent = TRUE;
-    m_isBeingDeleted = FALSE;
+    m_sizeSet = false;
+    m_hasVMT = false;
+    m_needParent = true;
+    m_isBeingDeleted = false;
 
-    m_noExpose = FALSE;
-    m_nativeSizeEvent = FALSE;
+    m_noExpose = false;
+    m_nativeSizeEvent = false;
 
-    m_hasScrolling = FALSE;
-    m_isScrolling = FALSE;
+    m_hasScrolling = false;
+    m_isScrolling = false;
 
     m_hAdjust = (GtkAdjustment*) NULL;
     m_vAdjust = (GtkAdjustment*) NULL;
@@ -2561,14 +2718,14 @@ void wxWindowGTK::Init()
     m_oldClientWidth =
     m_oldClientHeight = 0;
 
-    m_resizing = FALSE;
+    m_resizing = false;
 
     m_insertCallback = (wxInsertChildFunction) NULL;
 
-    m_acceptsFocus = FALSE;
-    m_hasFocus = FALSE;
+    m_acceptsFocus = false;
+    m_hasFocus = false;
 
-    m_clipPaintRegion = FALSE;
+    m_clipPaintRegion = false;
 
     m_needsStyleChange = false;
 
@@ -2614,7 +2771,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
         !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
     {
         wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
-        return FALSE;
+        return false;
     }
 
     m_insertCallback = wxInsertChildInWindow;
@@ -2658,7 +2815,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
     gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
 
     GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
-    m_acceptsFocus = TRUE;
+    m_acceptsFocus = true;
 
     // I _really_ don't want scrollbars in the beginning
     m_vAdjust->lower = 0.0;
@@ -2710,7 +2867,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
     PostCreation();
 
-    return TRUE;
+    return true;
 }
 
 wxWindowGTK::~wxWindowGTK()
@@ -2723,11 +2880,11 @@ wxWindowGTK::~wxWindowGTK()
     if ( g_delayedFocus == this )
         g_delayedFocus = NULL;
 
-    m_isBeingDeleted = TRUE;
-    m_hasVMT = FALSE;
+    m_isBeingDeleted = true;
+    m_hasVMT = false;
 
     if (m_widget)
-        Show( FALSE );
+        Show( false );
 
     DestroyChildren();
 
@@ -2757,7 +2914,7 @@ wxWindowGTK::~wxWindowGTK()
 
 bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const wxSize &size )
 {
-    wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
+    wxCHECK_MSG( !m_needParent || parent, false, wxT("Need complete parent.") );
 
     // Use either the given size, or the default if -1 is given.
     // See wxWindowBase for these functions.
@@ -2767,7 +2924,7 @@ bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const w
     m_x = (int)pos.x;
     m_y = (int)pos.y;
 
-    return TRUE;
+    return true;
 }
 
 void wxWindowGTK::PostCreation()
@@ -2826,11 +2983,11 @@ void wxWindowGTK::PostCreation()
     {
         if (m_focusWidget == NULL)
             m_focusWidget = m_widget;
-            
+
         gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_in_event",
             GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
 
-        gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_out_event",
+        gtk_signal_connect_after( GTK_OBJECT(m_focusWidget), "focus_out_event",
             GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
     }
 
@@ -2860,13 +3017,20 @@ void wxWindowGTK::PostCreation()
                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
     }
 
-    if ( !GTK_IS_COMBO(m_widget))
+    if (GTK_IS_COMBO(m_widget))
+    {
+        GtkCombo *gcombo = GTK_COMBO(m_widget);
+
+        gtk_signal_connect( GTK_OBJECT(gcombo->entry), "size_request",
+                            GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback),
+                            (gpointer) this );
+    }
+    else
     {
         // This is needed if we want to add our windows into native
-        // GTK control, such as the toolbar. With this callback, the
+        // GTK controls, 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.
+        // programmer). Sadly, it misbehaves for wxComboBox.
         gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback),
                             (gpointer) this );
@@ -2874,7 +3038,7 @@ void wxWindowGTK::PostCreation()
 
     InheritAttributes();
 
-    m_hasVMT = TRUE;
+    m_hasVMT = true;
 
     // unless the window was created initially hidden (i.e. Hide() had been
     // called before Create()), we should show it at GTK+ level as well
@@ -2902,6 +3066,8 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
 #ifdef __WXGTK20__
     gtk_signal_connect( GTK_OBJECT(widget), "scroll_event",
       GTK_SIGNAL_FUNC(gtk_window_wheel_callback), (gpointer)this );
+    g_signal_connect(widget, "popup_menu",
+        G_CALLBACK(wxgtk_window_popup_menu_callback), this);
 #endif
 
     gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
@@ -2915,7 +3081,7 @@ bool wxWindowGTK::Destroy()
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
 
-    m_hasVMT = FALSE;
+    m_hasVMT = false;
 
     return wxWindowBase::Destroy();
 }
@@ -2935,7 +3101,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
 */
 
     if (m_resizing) return; /* I don't like recursions */
-    m_resizing = TRUE;
+    m_resizing = true;
 
     int currentX, currentY;
     GetPosition(&currentX, &currentY);
@@ -2993,22 +3159,37 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
         if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
 
-        int border = 0;
+        int left_border = 0;
+        int right_border = 0;
+        int top_border = 0;
         int bottom_border = 0;
 
-#ifndef __WXGTK20__
+        /* the default button has a border around it */
         if (GTK_WIDGET_CAN_DEFAULT(m_widget))
         {
-            /* the default button has a border around it */
-            border = 6;
+#ifdef __WXGTK20__
+            GtkBorder *default_border = NULL;
+            gtk_widget_style_get( m_widget, "default_border", &default_border, NULL );
+            if (default_border)
+            {
+                left_border += default_border->left;
+                right_border += default_border->right;
+                top_border += default_border->top;
+                bottom_border += default_border->bottom;
+                g_free( default_border );
+            }
+#else
+            left_border = 6;
+            right_border = 6;
+            top_border = 6;
             bottom_border = 5;
-        }
 #endif
+        }
 
-        DoMoveWindow( m_x-border,
-                      m_y-border,
-                      m_width+2*border,
-                      m_height+border+bottom_border );
+        DoMoveWindow( m_x-top_border,
+                      m_y-left_border,
+                      m_width+left_border+right_border,
+                      m_height+top_border+bottom_border );
     }
 
     if (m_hasScrolling)
@@ -3036,7 +3217,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         GetEventHandler()->ProcessEvent( event );
     }
 
-    m_resizing = FALSE;
+    m_resizing = false;
 }
 
 void wxWindowGTK::OnInternalIdle()
@@ -3314,12 +3495,12 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
 
 bool wxWindowGTK::Show( bool show )
 {
-    wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
+    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
 
     if (!wxWindowBase::Show(show))
     {
         // nothing to do
-        return FALSE;
+        return false;
     }
 
     if (show)
@@ -3328,11 +3509,11 @@ bool wxWindowGTK::Show( bool show )
         gtk_widget_hide( m_widget );
 
     wxShowEvent eventShow(GetId(), show);
-    eventShow.m_eventObject = this;
+    eventShow.SetEventObject(this);
 
     GetEventHandler()->ProcessEvent(eventShow);
 
-    return TRUE;
+    return true;
 }
 
 static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
@@ -3354,12 +3535,12 @@ static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
 
 bool wxWindowGTK::Enable( bool enable )
 {
-    wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
+    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
 
     if (!wxWindowBase::Enable(enable))
     {
         // nothing to do
-        return FALSE;
+        return false;
     }
 
     gtk_widget_set_sensitive( m_widget, enable );
@@ -3368,7 +3549,7 @@ bool wxWindowGTK::Enable( bool enable )
 
     wxWindowNotifyEnable(this, enable);
 
-    return TRUE;
+    return true;
 }
 
 int wxWindowGTK::GetCharHeight() const
@@ -3440,17 +3621,17 @@ int wxWindowGTK::GetCharWidth() const
 }
 
 void wxWindowGTK::GetTextExtent( const wxString& string,
-                              int *x,
-                              int *y,
-                              int *descent,
-                              int *externalLeading,
-                              const wxFont *theFont ) const
+                                 int *x,
+                                 int *y,
+                                 int *descent,
+                                 int *externalLeading,
+                                 const wxFont *theFont ) const
 {
     wxFont fontToUse = theFont ? *theFont : GetFont();
 
     wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
-    if (string.IsEmpty())
+    if (string.empty())
     {
         if (x) (*x) = 0;
         if (y) (*y) = 0;
@@ -3534,7 +3715,7 @@ void wxWindowGTK::SetFocus()
 #endif
         if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
         {
-        
+
             if (!GTK_WIDGET_REALIZED(m_widget))
             {
                 // we can't set the focus to the widget now so we remember that
@@ -3555,7 +3736,7 @@ void wxWindowGTK::SetFocus()
                 gtk_widget_grab_focus (m_widget);
             }
         }
-        else 
+        else
 #ifndef __WXGTK20__
         if (GTK_IS_CONTAINER(m_widget))
         {
@@ -3578,7 +3759,7 @@ bool wxWindowGTK::AcceptsFocus() const
 
 bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
 {
-    wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
+    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
 
     wxWindowGTK *oldParent = m_parent,
              *newParent = (wxWindowGTK *)newParentBase;
@@ -3586,7 +3767,7 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
     wxASSERT( GTK_IS_WIDGET(m_widget) );
 
     if ( !wxWindowBase::Reparent(newParent) )
-        return FALSE;
+        return false;
 
     wxASSERT( GTK_IS_WIDGET(m_widget) );
 
@@ -3609,7 +3790,7 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
     /* reverse: prevent GTK from deleting the widget arbitrarily */
     gtk_widget_unref( m_widget );
 
-    return TRUE;
+    return true;
 }
 
 void wxWindowGTK::DoAddChild(wxWindowGTK *child)
@@ -3644,7 +3825,7 @@ void wxWindowGTK::RemoveChild(wxWindowBase *child)
     if (g_isIdle)
         wxapp_install_idle_handler();
 }
-    
+
 void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
 {
     wxWindowBase::DoMoveInTabOrder(win, move);
@@ -3660,15 +3841,15 @@ void wxWindowGTK::RealizeTabOrder()
         if (m_children.size() > 0)
         {
             GList *chain = NULL;
-            
+
             for (wxWindowList::const_iterator i = m_children.begin();
                     i != m_children.end(); ++i)
             {
                 chain = g_list_prepend(chain, (*i)->m_widget);
             }
-            
+
             chain = g_list_reverse(chain);
-            
+
             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow), chain);
             g_list_free(chain);
         }
@@ -3677,7 +3858,7 @@ void wxWindowGTK::RealizeTabOrder()
             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow));
         }
     }
-    
+
     m_dirtyTabOrder = false;
 }
 
@@ -3687,26 +3868,36 @@ void wxWindowGTK::Raise()
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
-    if (!m_widget->window) return;
-
-    gdk_window_raise( m_widget->window );
+    if (m_wxwindow && m_wxwindow->window)
+    {
+        gdk_window_raise( m_wxwindow->window );
+    }
+    else if (m_widget->window)
+    {
+        gdk_window_raise( m_widget->window );
+    }
 }
 
 void wxWindowGTK::Lower()
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
-    if (!m_widget->window) return;
-
-    gdk_window_lower( m_widget->window );
+    if (m_wxwindow && m_wxwindow->window)
+    {
+        gdk_window_lower( m_wxwindow->window );
+    }
+    else if (m_widget->window)
+    {
+        gdk_window_lower( m_widget->window );
+    }
 }
 
 bool wxWindowGTK::SetCursor( const wxCursor &cursor )
 {
-    wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
+    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
 
     if (cursor == m_cursor)
-       return FALSE;
+       return false;
 
     if (g_isIdle)
         wxapp_install_idle_handler();
@@ -3737,35 +3928,38 @@ void wxWindowGTK::WarpPointer( int x, int y )
 
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
-    if (!m_widget) return;
-    if (!m_widget->window) return;
+    if (!m_widget)
+        return;
+    if (!m_widget->window)
+        return;
 
 #ifndef __WXGTK20__
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    wxRect myRect(0,0,0,0);
+    wxRect myRect;
     if (m_wxwindow && rect)
     {
         myRect.SetSize(wxSize( m_wxwindow->allocation.width,
                                m_wxwindow->allocation.height));
-        myRect.Intersect(*rect);
-        if (!myRect.width || !myRect.height)
+        if ( myRect.Intersect(*rect).IsEmpty() )
+        {
             // nothing to do, rectangle is empty
             return;
+        }
+
         rect = &myRect;
     }
 
+    // schedule the area for later updating in GtkUpdate()
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
     {
         if (rect)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_clearRegion.Clear();
             m_clearRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
@@ -3775,7 +3969,6 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
         }
         else
@@ -3792,7 +3985,6 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     {
         if (m_wxwindow)
         {
-            // Schedule for later Updating in ::Update() or ::OnInternalIdle().
             m_updateRegion.Clear();
             m_updateRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
         }
@@ -3801,29 +3993,38 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
             gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
         }
     }
-#else
+#else // GTK+ 2
     if (m_wxwindow)
     {
+        GdkRectangle gdk_rect,
+                    *p;
         if (rect)
         {
-            GdkRectangle gdk_rect;
             gdk_rect.x = rect->x;
             gdk_rect.y = rect->y;
             gdk_rect.width = rect->width;
             gdk_rect.height = rect->height;
-            gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, &gdk_rect, TRUE );
+            p = &gdk_rect;
         }
-        else
+        else // invalidate everything
         {
-            gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, NULL, TRUE );
+            p = NULL;
         }
+
+        gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
     }
-#endif
+#endif // GTK+ 1/2
 }
 
 void wxWindowGTK::Update()
 {
     GtkUpdate();
+
+    // when we call Update() we really want to update the window immediately on
+    // screen, even if itmeans flushing the entire queue and hence slowing down
+    // everything -- but it should still be done, it's just that Update() should
+    // be called very rarely
+    gdk_flush();
 }
 
 void wxWindowGTK::GtkUpdate()
@@ -3835,6 +4036,16 @@ void wxWindowGTK::GtkUpdate()
     if (!m_updateRegion.IsEmpty())
         GtkSendPaintEvents();
 #endif
+
+    // for consistency with other platforms (and also because it's convenient
+    // to be able to update an entire TLW by calling Update() only once), we
+    // should also update all our children here
+    for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        node->GetData()->GtkUpdate();
+    }
 }
 
 void wxWindowGTK::GtkSendPaintEvents()
@@ -3849,39 +4060,40 @@ void wxWindowGTK::GtkSendPaintEvents()
     }
 
     // Clip to paint region in wxClientDC
-    m_clipPaintRegion = TRUE;
+    m_clipPaintRegion = true;
 
     // widget to draw on
     GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
 
-    if (GetThemeEnabled() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM)
+    if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM))
     {
         // find ancestor from which to steal background
-        wxWindow *parent = GetParent();
-        while (parent && !parent->IsTopLevel())
-            parent = parent->GetParent();
+        wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
         if (!parent)
             parent = (wxWindow*)this;
 
-        wxRegionIterator upd( m_updateRegion );
-        while (upd)
+        if (GTK_WIDGET_MAPPED(parent->m_widget))
         {
-            GdkRectangle rect;
-            rect.x = upd.GetX();
-            rect.y = upd.GetY();
-            rect.width = upd.GetWidth();
-            rect.height = upd.GetHeight();
-
-            gtk_paint_flat_box( parent->m_widget->style,
-                        pizza->bin_window,
-                        (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
-                        GTK_SHADOW_NONE,
-                        &rect,
-                        parent->m_widget,
-                        (char *)"base",
-                        0, 0, -1, -1 );
-
-            upd ++;
+            wxRegionIterator upd( m_updateRegion );
+            while (upd)
+            {
+                GdkRectangle rect;
+                rect.x = upd.GetX();
+                rect.y = upd.GetY();
+                rect.width = upd.GetWidth();
+                rect.height = upd.GetHeight();
+
+                gtk_paint_flat_box( parent->m_widget->style,
+                            pizza->bin_window,
+                            (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
+                            GTK_SHADOW_NONE,
+                            &rect,
+                            parent->m_widget,
+                            (char *)"base",
+                            0, 0, -1, -1 );
+
+                ++upd;
+            }
         }
     }
     else
@@ -3937,7 +4149,7 @@ void wxWindowGTK::GtkSendPaintEvents()
     paint_event.SetEventObject( this );
     GetEventHandler()->ProcessEvent( paint_event );
 
-    m_clipPaintRegion = FALSE;
+    m_clipPaintRegion = false;
 
 #ifndef __WXUNIVERSAL__
 #ifndef __WXGTK20__
@@ -4021,7 +4233,7 @@ void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
 
 bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
 {
-    wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
+    wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
 
     if (!wxWindowBase::SetBackgroundColour(colour))
         return false;
@@ -4042,13 +4254,13 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
 
 bool wxWindowGTK::SetForegroundColour( const wxColour &colour )
 {
-    wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
+    wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
 
     if (!wxWindowBase::SetForegroundColour(colour))
     {
         return false;
     }
-    
+
     if (colour.Ok())
     {
         // We need the pixel value e.g. for background clearing.
@@ -4076,7 +4288,7 @@ PangoContext *wxWindowGTK::GtkGetPangoX11Context()
     return m_x11Context;
 }
 #endif
+
 GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
 {
     // do we need to apply any changes at all?
@@ -4092,7 +4304,7 @@ GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
     if ( m_font.Ok() )
     {
 #ifdef __WXGTK20__
-        style->font_desc = 
+        style->font_desc =
             pango_font_description_copy( m_font.GetNativeFontInfo()->description );
 #else
         wxString xfontname = m_font.GetNativeFontInfo()->GetXFontName();
@@ -4103,13 +4315,13 @@ GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
     if ( m_foregroundColour.Ok() )
     {
         GdkColor *fg = m_foregroundColour.GetColor();
-        
+
         style->fg[GTK_STATE_NORMAL] = *fg;
         style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG;
-        
+
         style->fg[GTK_STATE_PRELIGHT] = *fg;
         style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG;
-        
+
         style->fg[GTK_STATE_ACTIVE] = *fg;
         style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG;
     }
@@ -4122,23 +4334,23 @@ GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
         style->base[GTK_STATE_NORMAL] = *bg;
         style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags)
             (style->color_flags[GTK_STATE_NORMAL] | GTK_RC_BG | GTK_RC_BASE);
-        
+
         style->bg[GTK_STATE_PRELIGHT] = *bg;
         style->base[GTK_STATE_PRELIGHT] = *bg;
         style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags)
             (style->color_flags[GTK_STATE_PRELIGHT] | GTK_RC_BG | GTK_RC_BASE);
-        
+
         style->bg[GTK_STATE_ACTIVE] = *bg;
         style->base[GTK_STATE_ACTIVE] = *bg;
         style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags)
             (style->color_flags[GTK_STATE_ACTIVE] | GTK_RC_BG | GTK_RC_BASE);
-        
+
         style->bg[GTK_STATE_INSENSITIVE] = *bg;
         style->base[GTK_STATE_INSENSITIVE] = *bg;
         style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags)
             (style->color_flags[GTK_STATE_INSENSITIVE] | GTK_RC_BG | GTK_RC_BASE);
     }
-    
+
     return style;
 }
 
@@ -4159,13 +4371,14 @@ void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style)
 {
     if (m_wxwindow)
         gtk_widget_modify_style(m_wxwindow, style);
-    gtk_widget_modify_style(m_widget, style);
+    else
+        gtk_widget_modify_style(m_widget, style);
 }
 
 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 {
     wxWindowBase::SetBackgroundStyle(style);
-    
+
     if (style == wxBG_STYLE_CUSTOM)
     {
         GdkWindow *window = (GdkWindow*) NULL;
@@ -4188,7 +4401,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
         else
             // Do in OnIdle, because the window is not yet available
             m_needsStyleChange = true;
-        
+
         // Don't apply widget style, or we get a grey background
     }
     else
@@ -4212,9 +4425,10 @@ void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting  )
     *is_waiting = FALSE;
 }
 
-static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
+void SetInvokingWindow( wxMenu *menu, wxWindow* win )
 {
     menu->SetInvokingWindow( win );
+
     wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
     while (node)
     {
@@ -4255,6 +4469,10 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 
     wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") );
 
+    // NOTE: if you change this code, you need to update
+    //       the same code in taskbar.cpp as well. This
+    //       is ugly code duplication, I know,
+
     SetInvokingWindow( menu, this );
 
     menu->UpdateUI();
@@ -4344,14 +4562,14 @@ bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window )
 
 bool wxWindowGTK::SetFont( const wxFont &font )
 {
-    wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
+    wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
 
     if (!wxWindowBase::SetFont(font))
         return false;
 
     // apply style change (forceStyle=true so that new style is applied
     // even if the font changed from valid to wxNullFont):
-    ApplyWidgetStyle(true);    
+    ApplyWidgetStyle(true);
 
     return true;
 }
@@ -4382,7 +4600,7 @@ void wxWindowGTK::DoCaptureMouse()
                       cursor->GetCursor(),
                       (guint32)GDK_CURRENT_TIME );
     g_captureWindow = this;
-    g_captureWindowHasMouse = TRUE;
+    g_captureWindowHasMouse = true;
 }
 
 void wxWindowGTK::DoReleaseMouse()
@@ -4413,7 +4631,7 @@ wxWindow *wxWindowBase::GetCapture()
 
 bool wxWindowGTK::IsRetained() const
 {
-    return FALSE;
+    return false;
 }
 
 void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
@@ -4423,7 +4641,7 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
 
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
 
-    m_hasScrolling = TRUE;
+    m_hasScrolling = true;
 
     if (orient == wxHORIZONTAL)
     {
@@ -4599,11 +4817,11 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
     }
 #endif
 
-    m_clipPaintRegion = TRUE;
+    m_clipPaintRegion = true;
 
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
 
-    m_clipPaintRegion = FALSE;
+    m_clipPaintRegion = false;
 }
 
 
@@ -4667,7 +4885,7 @@ bool wxWinModule::OnInit()
     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
 
-    return TRUE;
+    return true;
 }
 
 void wxWinModule::OnExit()