]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
disable eVC makefiles for sockets (no CLI targets possible on this platform)
[wxWidgets.git] / src / gtk / window.cpp
index 7b245651356fbe70816c65b41251937ab9c5c583..dc9ed38fe47e4d5a4b09c64ce714cebc3c779975 100644 (file)
 #ifndef WX_PRECOMP
     #include "wx/log.h"
     #include "wx/app.h"
-    #include "wx/frame.h"
+    #include "wx/toplevel.h"
     #include "wx/dcclient.h"
     #include "wx/menu.h"
     #include "wx/settings.h"
     #include "wx/msgdlg.h"
-    #include "wx/textctrl.h"
-    #include "wx/radiobut.h"
-    #include "wx/toolbar.h"
-    #include "wx/combobox.h"
-    #include "wx/layout.h"
     #include "wx/math.h"
 #endif
 
 #include "wx/tooltip.h"
 #include "wx/caret.h"
 #include "wx/fontutil.h"
-
-#ifdef __WXDEBUG__
-    #include "wx/thread.h"
-#endif
+#include "wx/sysopt.h"
 
 #include <ctype.h>
 
-// FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0
-#include <gtk/gtkversion.h>
-#if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0)
-    #undef GTK_DISABLE_DEPRECATED
-    #include <gtk/gtkcombo.h>
-    #define GTK_DISABLE_DEPRECATED
-#endif
-
 #include "wx/gtk/private.h"
 #include "wx/gtk/win_gtk.h"
 #include <gdk/gdkkeysyms.h>
    can find in m_widget (defined in wxWindow)
 
    When the class has a client area for drawing into and for containing children
-   it has to handle the client area widget (of the type GtkPizza, defined in
-   win_gtk.c), but there could be any number of widgets, handled by a class
+   it has to handle the client area widget (of the type wxPizza, defined in
+   win_gtk.cpp), but there could be any number of widgets, handled by a class.
    The common rule for all windows is only, that the widget that interacts with
    the rest of GTK must be referenced in m_widget and all other widgets must be
    children of this widget on the GTK level. The top-most widget, which also
    represents the client area, must be in the m_wxwindow field and must be of
-   the type GtkPizza.
+   the type wxPizza.
 
    As I said, the window classes that display a GTK native widget only have
    one widget, so in the case of e.g. the wxButton class m_widget holds a
    pointer to a GtkButton widget. But windows with client areas (for drawing
    and children) have a m_widget field that is a pointer to a GtkScrolled-
-   Window and a m_wxwindow field that is pointer to a GtkPizza and this
+   Window and a m_wxwindow field that is pointer to a wxPizza and this
    one is (in the GTK sense) a child of the GtkScrolledWindow.
 
    If the m_wxwindow field is set, then all input to this widget is inter-
    clicking on a scrollbar belonging to scrolled window will inevitably move
    the window. In wxWidgets, the scrollbar will only emit an event, send this
    to (normally) a wxScrolledWindow and that class will call ScrollWindow()
-   which actually moves the window and its sub-windows. Note that GtkPizza
+   which actually moves the window and its sub-windows. Note that wxPizza
    memorizes how much it has been scrolled but that wxWidgets forgets this
    so that the two coordinates systems have to be kept in synch. This is done
-   in various places using the pizza->xoffset and pizza->yoffset values.
+   in various places using the pizza->m_scroll_x and pizza->m_scroll_y values.
 
    III)
 
@@ -217,23 +201,10 @@ wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL;
 GdkEvent    *g_lastMouseEvent = (GdkEvent*) NULL;
 int          g_lastButtonNumber = 0;
 
-extern bool g_mainThreadLocked;
-
 //-----------------------------------------------------------------------------
 // debug
 //-----------------------------------------------------------------------------
 
-#ifdef __WXDEBUG__
-
-#if wxUSE_THREADS
-#   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
-#else
-#   define DEBUG_MAIN_THREAD
-#endif
-#else
-#define DEBUG_MAIN_THREAD
-#endif // Debug
-
 // the trace mask used for the focus debugging messages
 #define TRACE_FOCUS _T("focus")
 
@@ -316,101 +287,15 @@ static void GetScrollbarWidth(GtkWidget* widget, int& w, int& h)
     }
 }
 
-static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
-{
-    // wxUniversal widgets draw the borders and scrollbars themselves
-#ifndef __WXUNIVERSAL__
-    if (!win->m_hasVMT)
-        return;
-
-    int dx = 0;
-    int dy = 0;
-    if (GTK_WIDGET_NO_WINDOW (widget))
-    {
-        dx += widget->allocation.x;
-        dy += widget->allocation.y;
-    }
-
-    int x = dx;
-    int y = dy;
-
-    int dw = 0;
-    int dh = 0;
-    if (win->m_hasScrolling)
-    {
-        GetScrollbarWidth(widget, dw, dh);
-
-        if (win->GetLayoutDirection() == wxLayout_RightToLeft)
-        {
-            // This is actually wrong for old GTK+ version
-            // which do not display the scrollbar on the
-            // left side in RTL
-            x += dw;
-        }
-    }
-
-    int w = widget->allocation.width-dw;
-    int h = widget->allocation.height-dh;
-
-    if (win->HasFlag(wxRAISED_BORDER))
-    {
-        gtk_paint_shadow (widget->style,
-                          widget->window,
-                          GTK_STATE_NORMAL,
-                          GTK_SHADOW_OUT,
-                          NULL, NULL, NULL, // FIXME: No clipping?
-                          x, y, w, h );
-        return;
-    }
-
-    if (win->HasFlag(wxSUNKEN_BORDER))
-    {
-        gtk_paint_shadow (widget->style,
-                          widget->window,
-                          GTK_STATE_NORMAL,
-                          GTK_SHADOW_IN,
-                          NULL, NULL, NULL, // FIXME: No clipping?
-                          x, y, w, h );
-        return;
-    }
-
-    if (win->HasFlag(wxSIMPLE_BORDER))
-    {
-        GdkGC *gc;
-        gc = gdk_gc_new( widget->window );
-        gdk_gc_set_foreground( gc, &widget->style->black );
-        gdk_draw_rectangle( widget->window, gc, FALSE, x, y, w-1, h-1 );
-        g_object_unref (gc);
-        return;
-    }
-#endif // __WXUNIVERSAL__
-}
-
-//-----------------------------------------------------------------------------
-// "expose_event" of m_widget
-//-----------------------------------------------------------------------------
-
-extern "C" {
-static gboolean
-gtk_window_own_expose_callback( GtkWidget *widget,
-                                GdkEventExpose *gdk_event,
-                                wxWindowGTK *win )
-{
-    if (gdk_event->count == 0)
-        draw_frame(widget, win);
-    return false;
-}
-}
-
 //-----------------------------------------------------------------------------
 // "size_request" of m_widget
 //-----------------------------------------------------------------------------
 
 // make it extern because wxStaticText needs to disconnect this one
 extern "C" {
-void wxgtk_window_size_request_callback(GtkWidget *widget,
+void wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget),
                                         GtkRequisition *requisition,
-                                        wxWindow *win)
+                                        wxWindow * win)
 {
     int w, h;
     win->GetSize( &w, &h );
@@ -424,66 +309,16 @@ void wxgtk_window_size_request_callback(GtkWidget *widget,
 }
 }
 
-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->entry) )->size_request )
-        (gcombo->entry, &entry_req );
-
-    GtkRequisition button_req;
-    button_req.width = 2;
-    button_req.height = 2;
-    (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo->button) )->size_request )
-        (gcombo->button, &button_req );
-
-    requisition->width = w - button_req.width;
-    requisition->height = entry_req.height;
-}
-}
-
 //-----------------------------------------------------------------------------
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
 extern "C" {
 static gboolean
-gtk_window_expose_callback( GtkWidget *widget,
+gtk_window_expose_callback( GtkWidget*,
                             GdkEventExpose *gdk_event,
                             wxWindow *win )
 {
-    DEBUG_MAIN_THREAD
-
-    // 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)
-    {
-        // block expose events on GTK_WIDGET(pizza)->window,
-        //   all drawing is done on pizza->bin_window
-        return true;
-    }
-
-
 #if 0
     if (win->GetName())
     {
@@ -518,6 +353,66 @@ gtk_window_expose_callback( GtkWidget *widget,
 }
 }
 
+//-----------------------------------------------------------------------------
+// "expose_event" from m_widget, for drawing border
+//-----------------------------------------------------------------------------
+
+#ifndef __WXUNIVERSAL__
+
+GtkWidget* GetEntryWidget();
+
+extern "C" {
+static gboolean
+expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win)
+{
+    // if this event is not for the GdkWindow the border is drawn on
+    if (win->m_wxwindow == win->m_widget && gdk_event->window == widget->window)
+        return false;
+
+    int x = 0;
+    int y = 0;
+    // GtkScrolledWindow is GTK_NO_WINDOW
+    if (GTK_WIDGET_NO_WINDOW(widget))
+    {
+        x = widget->allocation.x;
+        y = widget->allocation.y;
+    }
+    int w = win->m_wxwindow->allocation.width;
+    int h = win->m_wxwindow->allocation.height;
+    if (win->HasFlag(wxBORDER_SIMPLE))
+    {
+        GdkGC* gc = gdk_gc_new(gdk_event->window);
+        gdk_gc_set_foreground(gc, &widget->style->black);
+        gdk_draw_rectangle(gdk_event->window, gc, false, x, y, w - 1, h - 1);
+        g_object_unref(gc);
+    }
+    else
+    {
+        GtkShadowType shadow = GTK_SHADOW_IN;
+        if (win->HasFlag(wxBORDER_RAISED))
+            shadow = GTK_SHADOW_OUT;
+
+        // Style detail to use
+        const char* detail;
+        if (widget == win->m_wxwindow)
+            // for non-scrollable wxWindows
+            detail = "entry";
+        else
+            // for scrollable ones
+            detail = "viewport";
+
+        GtkWidget* styleWidget = GetEntryWidget();
+        gtk_paint_shadow(
+           styleWidget->style, gdk_event->window, GTK_STATE_NORMAL,
+           shadow, NULL, styleWidget, detail, x, y, w, h);
+    }
+
+    // no further painting is needed for border-only GdkWindow
+    return win->m_wxwindow == win->m_widget;
+}
+}
+#endif // !__WXUNIVERSAL__
+
 //-----------------------------------------------------------------------------
 // "key_press_event" from any window
 //-----------------------------------------------------------------------------
@@ -980,13 +875,16 @@ gtk_window_key_press_callback( GtkWidget *widget,
                                GdkEventKey *gdk_event,
                                wxWindow *win )
 {
-    DEBUG_MAIN_THREAD
-
     if (!win->m_hasVMT)
         return FALSE;
     if (g_blockEventsOnDrag)
         return FALSE;
 
+    // GTK+ sends keypress events to the focus widget and then
+    // to all its parent and grandparent widget. We only want
+    // the key events from the focus widget.
+    if (!GTK_WIDGET_HAS_FOCUS(widget))
+        return FALSE;
 
     wxKeyEvent event( wxEVT_KEY_DOWN );
     bool ret = false;
@@ -995,7 +893,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
     if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
     {
         // Emit KEY_DOWN event
-        ret = win->GetEventHandler()->ProcessEvent( event );
+        ret = win->HandleWindowEvent( event );
     }
     else
     {
@@ -1004,18 +902,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
         return_after_IM = true;
     }
 
-    // 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 ))
+    if ((!ret) && (win->m_imData != NULL))
     {
         // 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.
@@ -1042,7 +929,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
             if (command != -1)
             {
                 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
-                ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
+                ret = ancestor->HandleWindowEvent( command_event );
                 break;
             }
             if (ancestor->IsTopLevel())
@@ -1101,13 +988,13 @@ gtk_window_key_press_callback( GtkWidget *widget,
             if (parent)
             {
                 event.SetEventType( wxEVT_CHAR_HOOK );
-                ret = parent->GetEventHandler()->ProcessEvent( event );
+                ret = parent->HandleWindowEvent( event );
             }
 
             if (!ret)
             {
                 event.SetEventType(wxEVT_CHAR);
-                ret = win->GetEventHandler()->ProcessEvent( event );
+                ret = win->HandleWindowEvent( event );
             }
         }
     }
@@ -1118,7 +1005,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
 
 extern "C" {
 static void
-gtk_wxwindow_commit_cb (GtkIMContext *context,
+gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context),
                         const gchar  *str,
                         wxWindow     *window)
 {
@@ -1177,13 +1064,13 @@ gtk_wxwindow_commit_cb (GtkIMContext *context,
         if (parent)
         {
             event.SetEventType( wxEVT_CHAR_HOOK );
-            ret = parent->GetEventHandler()->ProcessEvent( event );
+            ret = parent->HandleWindowEvent( event );
         }
 
         if (!ret)
         {
             event.SetEventType(wxEVT_CHAR);
-            ret = window->GetEventHandler()->ProcessEvent( event );
+            ret = window->HandleWindowEvent( event );
         }
     }
 }
@@ -1196,12 +1083,10 @@ gtk_wxwindow_commit_cb (GtkIMContext *context,
 
 extern "C" {
 static gboolean
-gtk_window_key_release_callback( GtkWidget *widget,
+gtk_window_key_release_callback( GtkWidget * WXUNUSED(widget),
                                  GdkEventKey *gdk_event,
                                  wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
     if (!win->m_hasVMT)
         return FALSE;
 
@@ -1233,22 +1118,15 @@ template<typename T> void InitMouseEvent(wxWindowGTK *win,
                                          T *gdk_event)
 {
     event.SetTimestamp( gdk_event->time );
-    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
-    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
-    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
-    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
-    event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
-    event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
-    event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
-    if (event.GetEventType() == wxEVT_MOUSEWHEEL)
-    {
-       event.m_linesPerAction = 3;
-       event.m_wheelDelta = 120;
-       if (((GdkEventButton*)gdk_event)->button == 4)
-           event.m_wheelRotation = 120;
-       else if (((GdkEventButton*)gdk_event)->button == 5)
-           event.m_wheelRotation = -120;
-    }
+    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_aux1Down = gdk_event->state & GDK_BUTTON4_MASK;
+    event.m_aux2Down = gdk_event->state & GDK_BUTTON5_MASK;
 
     wxPoint pt = win->GetClientAreaOrigin();
     event.m_x = (wxCoord)gdk_event->x - pt.x;
@@ -1257,7 +1135,7 @@ template<typename T> void InitMouseEvent(wxWindowGTK *win,
     if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft))
     {
         // origin in the upper right corner
-        int window_width = gtk_pizza_get_rtl_offset( GTK_PIZZA(win->m_wxwindow) );
+        int window_width = win->m_wxwindow->allocation.width;
         event.m_x = window_width - event.m_x;
     }
 
@@ -1307,9 +1185,9 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
 
     if (win->m_wxwindow)
     {
-        GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
-        xx += gtk_pizza_get_xoffset( pizza );
-        yy += gtk_pizza_get_yoffset( pizza );
+        wxPizza* pizza = WX_PIZZA(win->m_wxwindow);
+        xx += pizza->m_scroll_x;
+        yy += pizza->m_scroll_y;
     }
 
     wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
@@ -1371,13 +1249,11 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
 bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const
 {
     // nothing special at this level
-    return GetEventHandler()->ProcessEvent(event);
+    return HandleWindowEvent(event);
 }
 
 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
 {
-    DEBUG_MAIN_THREAD
-
     if (!m_hasVMT)
         return FALSE;
     if (g_blockEventsOnDrag)
@@ -1418,12 +1294,12 @@ static bool DoSendFocusEvents(wxWindow *win)
     // Notify the parent keeping track of focus for the kbd navigation
     // purposes that we got it.
     wxChildFocusEvent eventChildFocus(win);
-    (void)win->GetEventHandler()->ProcessEvent(eventChildFocus);
+    (void)win->HandleWindowEvent(eventChildFocus);
 
     wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId());
     eventFocus.SetEventObject(win);
 
-    return win->GetEventHandler()->ProcessEvent(eventFocus);
+    return win->HandleWindowEvent(eventFocus);
 }
 
 // all event handlers must have C linkage as they're called from GTK+ C code
@@ -1443,11 +1319,6 @@ gtk_window_button_press_callback( GtkWidget *widget,
 
     g_lastButtonNumber = gdk_event->button;
 
-    if (win->m_wxwindow && (g_focusWindow != win) && win->CanAcceptFocus())
-    {
-        gtk_widget_grab_focus( win->m_wxwindow );
-    }
-
     // GDK sends surplus button down events
     // before a double click event. We
     // need to filter these out.
@@ -1471,10 +1342,7 @@ gtk_window_button_press_callback( GtkWidget *widget,
 
     wxEventType event_type = wxEVT_NULL;
 
-    // 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
@@ -1484,7 +1352,6 @@ gtk_window_button_press_callback( GtkWidget *widget,
         display->button_click_time[1] = 0;
         display->button_click_time[0] = 0;
     }
-#endif // GTK 2+
 
     if (gdk_event->button == 1)
     {
@@ -1545,13 +1412,6 @@ gtk_window_button_press_callback( GtkWidget *widget,
                 ;
         }
     }
-    else if (gdk_event->button == 4 || gdk_event->button == 5)
-    {
-        if (gdk_event->type == GDK_BUTTON_PRESS )
-        {
-            event_type = wxEVT_MOUSEWHEEL;
-        }
-    }
 
     if ( event_type == wxEVT_NULL )
     {
@@ -1585,10 +1445,10 @@ gtk_window_button_press_callback( GtkWidget *widget,
     if ( ret )
         return TRUE;
 
-    if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() && 
-        (g_focusWindow != win) && win->CanAcceptFocus())
+    if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() &&
+        (g_focusWindow != win) /* && win->IsFocusable() */)
     {
-        gtk_widget_grab_focus( win->m_wxwindow );
+        win->SetFocus();
     }
 
     if (event_type == wxEVT_RIGHT_DOWN)
@@ -1674,7 +1534,7 @@ gtk_window_button_release_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 static gboolean
-gtk_window_motion_notify_callback( GtkWidget *widget,
+gtk_window_motion_notify_callback( GtkWidget * WXUNUSED(widget),
                                    GdkEventMotion *gdk_event,
                                    wxWindowGTK *win )
 {
@@ -1742,14 +1602,12 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
 }
 
 //-----------------------------------------------------------------------------
-// "scroll_event", (mouse wheel event)
+// "scroll_event" (mouse wheel event)
 //-----------------------------------------------------------------------------
 
 static gboolean
 window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
 {
-    DEBUG_MAIN_THREAD
-
     if (gdk_event->direction != GDK_SCROLL_UP &&
         gdk_event->direction != GDK_SCROLL_DOWN)
     {
@@ -1757,15 +1615,9 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
     }
 
     wxMouseEvent event(wxEVT_MOUSEWHEEL);
-    // 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);
+    InitMouseEvent(win, event, gdk_event);
+
+    // FIXME: Get these values from GTK or GDK
     event.m_linesPerAction = 3;
     event.m_wheelDelta = 120;
     if (gdk_event->direction == GDK_SCROLL_UP)
@@ -1773,14 +1625,6 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
     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 );
-
     return win->GTKProcessEvent(event);
 }
 
@@ -1800,12 +1644,10 @@ static gboolean wxgtk_window_popup_menu_callback(GtkWidget*, wxWindowGTK* win)
 //-----------------------------------------------------------------------------
 
 static gboolean
-gtk_window_focus_in_callback( GtkWidget *widget,
+gtk_window_focus_in_callback( GtkWidget * WXUNUSED(widget),
                               GdkEventFocus *WXUNUSED(event),
                               wxWindow *win )
 {
-    DEBUG_MAIN_THREAD
-
     if (win->m_imData)
         gtk_im_context_focus_in(win->m_imData->context);
 
@@ -1850,12 +1692,10 @@ gtk_window_focus_in_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 static gboolean
-gtk_window_focus_out_callback( GtkWidget *widget,
-                               GdkEventFocus *gdk_event,
+gtk_window_focus_out_callback( GtkWidget * WXUNUSED(widget),
+                               GdkEventFocus * WXUNUSED(gdk_event),
                                wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
     if (win->m_imData)
         gtk_im_context_focus_out(win->m_imData->context);
 
@@ -1905,11 +1745,10 @@ gtk_window_focus_out_callback( GtkWidget *widget,
 
 static gboolean
 wx_window_focus_callback(GtkWidget *widget,
-                         GtkDirectionType direction,
+                         GtkDirectionType WXUNUSED(direction),
                          wxWindowGTK *win)
 {
-    // the default handler for focus signal in GtkPizza (or, rather, in
-    // GtkScrolledWindow from which GtkPizza inherits this behaviour) sets
+    // the default handler for focus signal in GtkScrolledWindow sets
     // focus to the window itself even if it doesn't accept focus, i.e. has no
     // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing
     // the signal from reaching gtk_scrolled_window_focus() if we don't have
@@ -1975,8 +1814,6 @@ gtk_window_leave_callback( GtkWidget *widget,
     if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
 
     wxMouseEvent event( wxEVT_LEAVE_WINDOW );
-    event.SetTimestamp( gdk_event->time );
-    event.SetEventObject( win );
 
     int x = 0;
     int y = 0;
@@ -1984,17 +1821,7 @@ gtk_window_leave_callback( GtkWidget *widget,
 
     gdk_window_get_pointer( widget->window, &x, &y, &state );
 
-    event.m_shiftDown = (state & GDK_SHIFT_MASK) != 0;
-    event.m_controlDown = (state & GDK_CONTROL_MASK) != 0;
-    event.m_altDown = (state & GDK_MOD1_MASK) != 0;
-    event.m_metaDown = (state & GDK_MOD2_MASK) != 0;
-    event.m_leftDown = (state & GDK_BUTTON1_MASK) != 0;
-    event.m_middleDown = (state & GDK_BUTTON2_MASK) != 0;
-    event.m_rightDown = (state & GDK_BUTTON3_MASK) != 0;
-
-    wxPoint pt = win->GetClientAreaOrigin();
-    event.m_x = x + pt.x;
-    event.m_y = y + pt.y;
+    InitMouseEvent(win, event, gdk_event);
 
     return win->GTKProcessEvent(event);
 }
@@ -2020,9 +1847,7 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
         wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient);
         event.SetEventObject(win);
 
-        win->m_blockValueChanged[dir] = true;
         win->GTKProcessEvent(event);
-        win->m_blockValueChanged[dir] = false;
     }
 }
 
@@ -2033,8 +1858,6 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
 static gboolean
 gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win)
 {
-    DEBUG_MAIN_THREAD
-
     g_blockEventsOnScroll = true;
     win->m_mouseButtonDown = true;
 
@@ -2054,9 +1877,10 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
 
         const int orient = wxWindow::OrientFromScrollDir(
                                         win->ScrollDirFromRange(range));
-        wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
-        event.SetEventObject(win);
-        win->GTKProcessEvent(event);
+        wxScrollWinEvent evt(wxEVT_SCROLLWIN_THUMBRELEASE,
+                                win->GetScrollPos(orient), orient);
+        evt.SetEventObject(win);
+        win->GTKProcessEvent(evt);
     }
 }
 
@@ -2067,8 +1891,6 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
 static gboolean
 gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* win)
 {
-    DEBUG_MAIN_THREAD
-
     g_blockEventsOnScroll = false;
     win->m_mouseButtonDown = false;
     // If thumb tracking
@@ -2089,15 +1911,12 @@ gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* w
 //-----------------------------------------------------------------------------
 
 static void
-gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
+gtk_window_realized_callback(GtkWidget* widget, wxWindow* win)
 {
-    DEBUG_MAIN_THREAD
-
     if (win->m_imData)
     {
-        GtkPizza *pizza = GTK_PIZZA( m_widget );
         gtk_im_context_set_client_window( win->m_imData->context,
-                                          pizza->bin_window );
+                                          widget->window);
     }
 
     // We cannot set colours and fonts before the widget
@@ -2116,39 +1935,105 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 }
 
 //-----------------------------------------------------------------------------
-// "size_allocate"
+// "size_allocate" from m_wxwindow or m_widget
 //-----------------------------------------------------------------------------
 
-static
-void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
-                               GtkAllocation *alloc,
-                               wxWindow *win )
+static void
+size_allocate(GtkWidget*, GtkAllocation* alloc, wxWindow* win)
 {
-    int client_width = 0;
-    int client_height = 0;
-    win->GetClientSize( &client_width, &client_height );
-    if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
-        return;
+    int w = alloc->width;
+    int h = alloc->height;
+    if (win->m_wxwindow)
+    {
+        int border_x, border_y;
+        WX_PIZZA(win->m_wxwindow)->get_border_widths(border_x, border_y);
+        w -= 2 * border_x;
+        h -= 2 * border_y;
+        if (w < 0) w = 0;
+        if (h < 0) h = 0;
+    }
+    if (win->m_oldClientWidth != w || win->m_oldClientHeight != h)
+    {
+        win->m_oldClientWidth  = w;
+        win->m_oldClientHeight = h;
+        // this callback can be connected to m_wxwindow,
+        // so always get size from m_widget->allocation
+        win->m_width  = win->m_widget->allocation.width;
+        win->m_height = win->m_widget->allocation.height;
+        if (!win->m_nativeSizeEvent)
+        {
+            wxSizeEvent event(win->GetSize(), win->GetId());
+            event.SetEventObject(win);
+            win->GTKProcessEvent(event);
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// "grab_broken"
+//-----------------------------------------------------------------------------
 
-    if ( !client_width && !client_height )
+#if GTK_CHECK_VERSION(2, 8, 0)
+static gboolean
+gtk_window_grab_broken( GtkWidget*,
+                        GdkEventGrabBroken *event,
+                        wxWindow *win )
+{
+    // Mouse capture has been lost involuntarily, notify the application
+    if(!event->keyboard && wxWindow::GetCapture() == win)
     {
-        // the window is currently unmapped, don't generate size events
-        return;
+        wxMouseCaptureLostEvent evt( win->GetId() );
+        evt.SetEventObject( win );
+        win->HandleWindowEvent( evt );
     }
+    return false;
+}
+#endif
 
-    win->m_oldClientWidth = client_width;
-    win->m_oldClientHeight = client_height;
+//-----------------------------------------------------------------------------
+// "style_set"
+//-----------------------------------------------------------------------------
 
-    if (!win->m_nativeSizeEvent)
+static
+void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget),
+                               GtkStyle *previous_style,
+                               wxWindow* win )
+{
+    if (win && previous_style)
     {
-        wxSizeEvent event( win->GetSize(), win->GetId() );
-        event.SetEventObject( win );
+        wxSysColourChangedEvent event;
+        event.SetEventObject(win);
+
         win->GTKProcessEvent( event );
     }
 }
 
 } // extern "C"
 
+// Helper to suspend colour change event event processing while we change a widget's style
+class wxSuspendStyleEvents
+{
+public:
+    wxSuspendStyleEvents(wxWindow* win)
+    {
+        m_win = NULL;
+        if (win->m_wxwindow && win->IsTopLevel())
+        {
+            m_win = win;
+            g_signal_handlers_block_by_func(
+                m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win);
+        }
+    }
+    ~wxSuspendStyleEvents()
+    {
+        if (m_win)
+            g_signal_handlers_unblock_by_func(
+                m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win);
+    }
+
+    wxWindow* m_win;
+};
+
 // ----------------------------------------------------------------------------
 // this wxWindowBase function is implemented here (in platform-specific file)
 // because it is static and so couldn't be made virtual
@@ -2175,16 +2060,14 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
 {
     /* the window might have been scrolled already, do we
        have to adapt the position */
-    GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
-    child->m_x += gtk_pizza_get_xoffset( pizza );
-    child->m_y += gtk_pizza_get_yoffset( pizza );
+    wxPizza* pizza = WX_PIZZA(parent->m_wxwindow);
+    child->m_x += pizza->m_scroll_x;
+    child->m_y += pizza->m_scroll_y;
 
-    gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
-                     child->m_widget,
-                     child->m_x,
-                     child->m_y,
-                     child->m_width,
-                     child->m_height );
+    gtk_widget_set_size_request(
+        child->m_widget, child->m_width, child->m_height);
+    gtk_fixed_put(
+        GTK_FIXED(parent->m_wxwindow), child->m_widget, child->m_x, child->m_y);
 }
 
 //-----------------------------------------------------------------------------
@@ -2212,6 +2095,8 @@ wxMouseState wxGetMouseState()
     ms.SetLeftDown(mask & GDK_BUTTON1_MASK);
     ms.SetMiddleDown(mask & GDK_BUTTON2_MASK);
     ms.SetRightDown(mask & GDK_BUTTON3_MASK);
+    ms.SetAux1Down(mask & GDK_BUTTON4_MASK);
+    ms.SetAux2Down(mask & GDK_BUTTON5_MASK);
 
     ms.SetControlDown(mask & GDK_CONTROL_MASK);
     ms.SetShiftDown(mask & GDK_SHIFT_MASK);
@@ -2257,21 +2142,17 @@ void wxWindowGTK::Init()
     m_hasScrolling = false;
     m_isScrolling = false;
     m_mouseButtonDown = false;
-    m_blockScrollEvent = false;
 
     // initialize scrolling stuff
     for ( int dir = 0; dir < ScrollDir_Max; dir++ )
     {
         m_scrollBar[dir] = NULL;
         m_scrollPos[dir] = 0;
-        m_blockValueChanged[dir] = false;
     }
 
     m_oldClientWidth =
     m_oldClientHeight = 0;
 
-    m_resizing = false;
-
     m_insertCallback = wxInsertChildInWindow;
 
     m_hasFocus = false;
@@ -2310,6 +2191,11 @@ bool wxWindowGTK::Create( wxWindow *parent,
                           long style,
                           const wxString &name  )
 {
+    // Get default border
+    wxBorder border = GetBorder(style);
+    style &= ~wxBORDER_MASK;
+    style |= border;
+
     if (!PreCreation( parent, pos, size ) ||
         !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
     {
@@ -2317,30 +2203,12 @@ bool wxWindowGTK::Create( wxWindow *parent,
         return false;
     }
 
-    if (!HasFlag(wxHSCROLL) && !HasFlag(wxVSCROLL))
-    {
-        m_wxwindow = gtk_pizza_new_no_scroll();
-
-#ifndef __WXUNIVERSAL__
-        if (HasFlag(wxSIMPLE_BORDER))
-            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
-        else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
-            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
-#endif // __WXUNIVERSAL__
 
+    m_wxwindow = wxPizza::New(m_windowStyle);
+    if (!HasFlag(wxHSCROLL) && !HasFlag(wxVSCROLL))
         m_widget = m_wxwindow;
-    }
     else
     {
-        m_wxwindow = gtk_pizza_new();
-
-#ifndef __WXUNIVERSAL__
-        if (HasFlag(wxSIMPLE_BORDER))
-            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
-        else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
-            gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
-#endif // __WXUNIVERSAL__
-
         m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
 
         GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
@@ -2400,7 +2268,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
             g_signal_handler_block(m_scrollBar[dir], handler_id);
 
             // these handlers get notified when scrollbar slider moves
-            g_signal_connect(m_scrollBar[dir], "value_changed",
+            g_signal_connect_after(m_scrollBar[dir], "value_changed",
                          G_CALLBACK(gtk_scrollbar_value_changed), this);
         }
 
@@ -2496,7 +2364,7 @@ void wxWindowGTK::PostCreation()
                               G_CALLBACK (gtk_window_expose_callback), this);
 
             if (GetLayoutDirection() == wxLayout_LeftToRight)
-                gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
+                gtk_widget_set_redraw_on_allocate(m_wxwindow, HasFlag(wxFULL_REPAINT_ON_RESIZE));
         }
 
         // Create input method handler
@@ -2508,9 +2376,14 @@ void wxWindowGTK::PostCreation()
         g_signal_connect (m_imData->context, "commit",
                           G_CALLBACK (gtk_wxwindow_commit_cb), this);
 
-        // these are called when the "sunken" or "raised" borders are drawn
-        g_signal_connect (m_widget, "expose_event",
-                          G_CALLBACK (gtk_window_own_expose_callback), this);
+        // border drawing
+#ifndef __WXUNIVERSAL__
+        if (HasFlag(wxPizza::BORDER_STYLES))
+        {
+            g_signal_connect(m_widget, "expose_event",
+                G_CALLBACK(expose_event_border), this);
+        }
+#endif
     }
 
     // focus handling
@@ -2555,31 +2428,46 @@ void wxWindowGTK::PostCreation()
     g_signal_connect (connect_widget, "realize",
                       G_CALLBACK (gtk_window_realized_callback), this);
 
-    if (m_wxwindow)
+    if (!IsTopLevel())
     {
-        // Catch native resize events
-        g_signal_connect (m_wxwindow, "size_allocate",
-                          G_CALLBACK (gtk_window_size_callback), this);
+        g_signal_connect(m_wxwindow ? m_wxwindow : m_widget, "size_allocate",
+            G_CALLBACK(size_allocate), this);
     }
 
-    if (GTK_IS_COMBO(m_widget))
+    if (m_wxwindow)
     {
-        GtkCombo *gcombo = GTK_COMBO(m_widget);
+#if GTK_CHECK_VERSION(2, 8, 0)
+        if (!gtk_check_version(2,8,0))
+        {
+            // Make sure we can notify the app when mouse capture is lost
+            g_signal_connect (m_wxwindow, "grab_broken_event",
+                          G_CALLBACK (gtk_window_grab_broken), this);
+        }
+#endif
+    }
 
-        g_signal_connect (gcombo->entry, "size_request",
-                          G_CALLBACK (wxgtk_combo_size_request_callback),
-                          this);
+    if ( connect_widget != m_wxwindow )
+    {
+#if GTK_CHECK_VERSION(2, 8, 0)
+        if (!gtk_check_version(2,8,0))
+        {
+            // Make sure we can notify app code when mouse capture is lost
+            g_signal_connect (connect_widget, "grab_broken_event",
+                        G_CALLBACK (gtk_window_grab_broken), this);
+        }
+#endif
     }
+
 #ifdef GTK_IS_FILE_CHOOSER_BUTTON
-    else if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
+    if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
     {
         // If we connect to the "size_request" signal of a GtkFileChooserButton
         // then that control won't be sized properly when placed inside sizers
         // (this can be tested removing this elseif and running XRC or WIDGETS samples)
         // FIXME: what should be done here ?
-    }
+    } else
 #endif
-    else if ( !IsTopLevel() ) // top level windows use their own callback
+    if ( !IsTopLevel() ) // top level windows use their own callback
     {
         // This is needed if we want to add our windows into native
         // GTK controls, such as the toolbar. With this callback, the
@@ -2622,6 +2510,10 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
                       G_CALLBACK (gtk_window_enter_callback), this);
     g_signal_connect (widget, "leave_notify_event",
                       G_CALLBACK (gtk_window_leave_callback), this);
+
+    if (IsTopLevel() && m_wxwindow)
+        g_signal_connect (m_wxwindow, "style_set",
+                              G_CALLBACK (gtk_window_style_set_callback), this);
 }
 
 bool wxWindowGTK::Destroy()
@@ -2635,9 +2527,9 @@ bool wxWindowGTK::Destroy()
 
 void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
 {
+    gtk_widget_set_size_request(m_widget, width, height);
     // inform the parent to perform the move
-    gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
-
+    WX_PIZZA(m_parent->m_wxwindow)->move(m_widget, x, y);
 }
 
 void wxWindowGTK::ConstrainSize()
@@ -2662,9 +2554,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
     wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") );
 
-    if (m_resizing) return; /* I don't like recursions */
-    m_resizing = true;
-
     int currentX, currentY;
     GetPosition(&currentX, &currentY);
     if (x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
@@ -2684,6 +2573,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
             height = sizeBest.y;
     }
 
+    const wxSize oldSize(m_width, m_height);
     if (width != -1)
         m_width = width;
     if (height != -1)
@@ -2691,36 +2581,11 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
 
     ConstrainSize();
 
-#if wxUSE_TOOLBAR_NATIVE
-    if (wxDynamicCast(GetParent(), wxToolBar))
-    {
-       // don't take the x,y values, they're wrong because toolbar sets them
-       GtkWidget  *widget = m_widget;
-       gtk_widget_set_size_request (widget, m_width, m_height);
-    }
-    else
-#endif
-    if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
+    if (m_parent->m_wxwindow)
     {
-        // don't set the size for children of wxNotebook, just take the values.
-        m_x = x;
-        m_y = y;
-        m_width = width;
-        m_height = height;
-    }
-    else
-    {
-        GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
-        if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
-        {
-            if (x != -1) m_x = x + gtk_pizza_get_xoffset( pizza );
-            if (y != -1) m_y = y + gtk_pizza_get_yoffset( pizza );
-        }
-        else
-        {
-            m_x = x + gtk_pizza_get_xoffset( pizza );
-            m_y = y + gtk_pizza_get_yoffset( pizza );
-        }
+        wxPizza* pizza = WX_PIZZA(m_parent->m_wxwindow);
+        m_x = x + pizza->m_scroll_x;
+        m_y = y + pizza->m_scroll_y;
 
         int left_border = 0;
         int right_border = 0;
@@ -2738,42 +2603,30 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
                 right_border += default_border->right;
                 top_border += default_border->top;
                 bottom_border += default_border->bottom;
-                g_free( default_border );
+                gtk_border_free( default_border );
             }
         }
 
-        DoMoveWindow( m_x-top_border,
-                      m_y-left_border,
+        DoMoveWindow( m_x - left_border,
+                      m_y - top_border,
                       m_width+left_border+right_border,
                       m_height+top_border+bottom_border );
     }
 
-    if (m_hasScrolling)
+    if (m_width != oldSize.x || m_height != oldSize.y)
     {
-        /* Sometimes the client area changes size without the
-           whole windows's size changing, but if the whole
-           windows's size doesn't change, no wxSizeEvent will
-           normally be sent. Here we add an extra test if
-           the client test has been changed and this will
-           be used then. */
+        // update these variables to keep size_allocate handler
+        // from sending another size event for this change
         GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
-    }
-
-/*
-    wxPrintf( "OnSize sent from " );
-    if (GetClassInfo() && GetClassInfo()->GetClassName())
-        wxPrintf( GetClassInfo()->GetClassName() );
-    wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
-*/
 
-    if (!m_nativeSizeEvent)
-    {
-        wxSizeEvent event( wxSize(m_width,m_height), GetId() );
-        event.SetEventObject( this );
-        GetEventHandler()->ProcessEvent( event );
+        gtk_widget_queue_resize(m_widget);
+        if (!m_nativeSizeEvent)
+        {
+            wxSizeEvent event( wxSize(m_width,m_height), GetId() );
+            event.SetEventObject( this );
+            HandleWindowEvent( event );
+        }
     }
-
-    m_resizing = false;
 }
 
 bool wxWindowGTK::GtkShowFromOnIdle()
@@ -2789,7 +2642,7 @@ bool wxWindowGTK::GtkShowFromOnIdle()
         gtk_widget_show( m_widget );
         wxShowEvent eventShow(GetId(), true);
         eventShow.SetEventObject(this);
-        GetEventHandler()->ProcessEvent(eventShow);
+        HandleWindowEvent(eventShow);
         m_showOnIdle = false;
         return true;
     }
@@ -2828,7 +2681,7 @@ void wxWindowGTK::OnInternalIdle()
 
         if (m_wxwindow && (m_wxwindow != m_widget))
         {
-            GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
+            GdkWindow *window = m_wxwindow->window;
             if (window)
                 gdk_window_set_cursor( window, cursor.GetCursor() );
 
@@ -2848,7 +2701,7 @@ void wxWindowGTK::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate(this))
+    if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
@@ -2884,9 +2737,10 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
         if (m_hasScrolling)
             GetScrollbarWidth(m_widget, dw, dh);
 
-        const int border = GTK_CONTAINER(m_wxwindow)->border_width;
-        dw += 2 * border;
-        dh += 2 * border;
+        int border_x, border_y;
+        WX_PIZZA(m_wxwindow)->get_border_widths(border_x, border_y);
+        dw += 2 * border_x;
+        dh += 2 * border_y;
 
         w -= dw;
         h -= dh;
@@ -2906,18 +2760,18 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
 
     int dx = 0;
     int dy = 0;
-    if (m_parent && m_parent->m_wxwindow)
+    if (!IsTopLevel() && m_parent && m_parent->m_wxwindow)
     {
-        GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
-        dx = gtk_pizza_get_xoffset( pizza );
-        dy = gtk_pizza_get_yoffset( pizza );
+        wxPizza* pizza = WX_PIZZA(m_parent->m_wxwindow);
+        dx = pizza->m_scroll_x;
+        dy = pizza->m_scroll_y;
     }
 
     if (m_x == -1 && m_y == -1)
     {
         GdkWindow *source = (GdkWindow *) NULL;
         if (m_wxwindow)
-            source = GTK_PIZZA(m_wxwindow)->bin_window;
+            source = m_wxwindow->window;
         else
             source = m_widget->window;
 
@@ -2947,7 +2801,7 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const
 
     GdkWindow *source = (GdkWindow *) NULL;
     if (m_wxwindow)
-        source = GTK_PIZZA(m_wxwindow)->bin_window;
+        source = m_wxwindow->window;
     else
         source = m_widget->window;
 
@@ -2984,7 +2838,7 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
 
     GdkWindow *source = (GdkWindow *) NULL;
     if (m_wxwindow)
-        source = GTK_PIZZA(m_wxwindow)->bin_window;
+        source = m_wxwindow->window;
     else
         source = m_widget->window;
 
@@ -3021,22 +2875,19 @@ bool wxWindowGTK::Show( bool show )
         return false;
     }
 
-    if (show)
+    if (show && m_showOnIdle)
     {
-        if (!m_showOnIdle)
-        {
-            gtk_widget_show( m_widget );
-            wxShowEvent eventShow(GetId(), show);
-            eventShow.SetEventObject(this);
-            GetEventHandler()->ProcessEvent(eventShow);
-        }
+        // deferred
     }
     else
     {
-        gtk_widget_hide( m_widget );
+        if (show)
+            gtk_widget_show(m_widget);
+        else
+            gtk_widget_hide(m_widget);
         wxShowEvent eventShow(GetId(), show);
         eventShow.SetEventObject(this);
-        GetEventHandler()->ProcessEvent(eventShow);
+        HandleWindowEvent(eventShow);
     }
 
     return true;
@@ -3058,9 +2909,7 @@ int wxWindowGTK::GetCharHeight() const
     wxFont font = GetFont();
     wxCHECK_MSG( font.Ok(), 12, wxT("invalid font") );
 
-    PangoContext *context = NULL;
-    if (m_widget)
-        context = gtk_widget_get_pango_context( m_widget );
+    PangoContext* context = gtk_widget_get_pango_context(m_widget);
 
     if (!context)
         return 0;
@@ -3086,9 +2935,7 @@ int wxWindowGTK::GetCharWidth() const
     wxFont font = GetFont();
     wxCHECK_MSG( font.Ok(), 8, wxT("invalid font") );
 
-    PangoContext *context = NULL;
-    if (m_widget)
-        context = gtk_widget_get_pango_context( m_widget );
+    PangoContext* context = gtk_widget_get_pango_context(m_widget);
 
     if (!context)
         return 0;
@@ -3189,16 +3036,26 @@ void wxWindowGTK::SetFocus()
 
     if (m_wxwindow)
     {
+        // wxWindow::SetFocus() should really set the focus to
+        // this control, whatever the flags are
+        if (!GTK_WIDGET_CAN_FOCUS(m_wxwindow))
+            GTK_WIDGET_SET_FLAGS(m_wxwindow, GTK_CAN_FOCUS);
+
         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
         {
             gtk_widget_grab_focus (m_wxwindow);
         }
     }
-    else if (m_widget)
+    else
     {
+        // wxWindow::SetFocus() should really set the focus to
+        // this control, whatever the flags are
+        if (!GTK_WIDGET_CAN_FOCUS(m_widget))
+            GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS);
+
         if (GTK_IS_CONTAINER(m_widget))
         {
-            if (IsKindOf(CLASSINFO(wxRadioButton)))
+            if (GTK_IS_RADIO_BUTTON(m_widget))
             {
                 gtk_widget_grab_focus (m_widget);
                 return;
@@ -3378,11 +3235,11 @@ wxWindowGTK::AdjustForLayoutDirection(wxCoord x,
                                       wxCoord WXUNUSED(width),
                                       wxCoord WXUNUSED(widthTotal)) const
 {
-    // We now mirrors the coordinates of RTL windows in GtkPizza
+    // We now mirror the coordinates of RTL windows in wxPizza
     return x;
 }
 
-void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
+void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, WindowOrder move)
 {
     wxWindowBase::DoMoveInTabOrder(win, move);
     m_dirtyTabOrder = true;
@@ -3399,7 +3256,7 @@ bool wxWindowGTK::DoNavigateIn(int flags)
     }
     else // navigate inside the container
     {
-        wxWindow *parent = wxGetTopLevelParent(this);
+        wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
         wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") );
 
         GtkDirectionType dir;
@@ -3561,7 +3418,7 @@ void wxWindowGTK::WarpPointer( int x, int y )
 
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
-        window = GTK_PIZZA(m_wxwindow)->bin_window;
+        window = m_wxwindow->window;
     else
         window = GetConnectWidget()->window;
 
@@ -3612,7 +3469,8 @@ bool wxWindowGTK::ScrollPages(int pages)
     return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Page, pages);
 }
 
-void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
+void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
+                          const wxRect *rect)
 {
     if (!m_widget)
         return;
@@ -3621,7 +3479,7 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 
     if (m_wxwindow)
     {
-        if (!GTK_PIZZA(m_wxwindow)->bin_window) return;
+        if (m_wxwindow->window == NULL) return;
 
         GdkRectangle gdk_rect,
                     *p;
@@ -3641,7 +3499,7 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
             p = NULL;
         }
 
-        gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
+        gdk_window_invalidate_rect(m_wxwindow->window, p, true);
     }
 }
 
@@ -3658,8 +3516,8 @@ void wxWindowGTK::Update()
 
 void wxWindowGTK::GtkUpdate()
 {
-    if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
-        gdk_window_process_updates( GTK_PIZZA(m_wxwindow)->bin_window, FALSE );
+    if (m_wxwindow && m_wxwindow->window)
+        gdk_window_process_updates(m_wxwindow->window, false);
     if (m_widget && m_widget->window && (m_wxwindow != m_widget))
         gdk_window_process_updates( m_widget->window, FALSE );
 
@@ -3707,8 +3565,7 @@ void wxWindowGTK::GtkSendPaintEvents()
         m_updateRegion.Clear();
 
         gint width;
-        gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window,
-                                 NULL, NULL, &width, NULL, NULL );
+        gdk_drawable_get_size(m_wxwindow->window, &width, NULL);
 
         wxRegionIterator upd( m_nativeUpdateRegion );
         while (upd)
@@ -3726,9 +3583,6 @@ void wxWindowGTK::GtkSendPaintEvents()
         }
     }
 
-    // widget to draw on
-    GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
-
     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM))
     {
         // find ancestor from which to steal background
@@ -3748,7 +3602,7 @@ void wxWindowGTK::GtkSendPaintEvents()
                 rect.height = upd.GetHeight();
 
                 gtk_paint_flat_box( parent->m_widget->style,
-                            pizza->bin_window,
+                            m_wxwindow->window,
                             (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
                             GTK_SHADOW_NONE,
                             &rect,
@@ -3765,19 +3619,27 @@ void wxWindowGTK::GtkSendPaintEvents()
         wxWindowDC dc( (wxWindow*)this );
         dc.SetClippingRegion( m_updateRegion );
 
+        // Work around gtk-qt <= 0.60 bug whereby the window colour
+        // remains grey
+        if (GetBackgroundStyle() == wxBG_STYLE_COLOUR && GetBackgroundColour().Ok() && wxSystemOptions::GetOptionInt(wxT("gtk.window.force-background-colour")) == 1)
+        {
+            dc.SetBackground(wxBrush(GetBackgroundColour()));
+            dc.Clear();
+        }
+
         wxEraseEvent erase_event( GetId(), &dc );
         erase_event.SetEventObject( this );
 
-        GetEventHandler()->ProcessEvent(erase_event);
+        HandleWindowEvent(erase_event);
     }
 
     wxNcPaintEvent nc_paint_event( GetId() );
     nc_paint_event.SetEventObject( this );
-    GetEventHandler()->ProcessEvent( nc_paint_event );
+    HandleWindowEvent( nc_paint_event );
 
     wxPaintEvent paint_event( GetId() );
     paint_event.SetEventObject( this );
-    GetEventHandler()->ProcessEvent( paint_event );
+    HandleWindowEvent( paint_event );
 
     m_clipPaintRegion = false;
 
@@ -3950,6 +3812,8 @@ void wxWindowGTK::ApplyWidgetStyle(bool forceStyle)
 
 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style)
 {
+    wxSuspendStyleEvents s(static_cast<wxWindow*>(this));
+
     if (m_wxwindow)
         gtk_widget_modify_style(m_wxwindow, style);
     else
@@ -3962,11 +3826,16 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 
     if (style == wxBG_STYLE_CUSTOM)
     {
-        GdkWindow *window = (GdkWindow*) NULL;
-        if (m_wxwindow)
-            window = GTK_PIZZA(m_wxwindow)->bin_window;
+        GdkWindow *window;
+        if ( m_wxwindow )
+        {
+            window = m_wxwindow->window;
+        }
         else
-            window = GetConnectWidget()->window;
+        {
+            GtkWidget * const w = GetConnectWidget();
+            window = w ? w->window : NULL;
+        }
 
         if (window)
         {
@@ -3979,9 +3848,11 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 #endif
             m_needsStyleChange = false;
         }
-        else
+        else // window not realized yet
+        {
             // Do in OnIdle, because the window is not yet available
             m_needsStyleChange = true;
+        }
 
         // Don't apply widget style, or we get a grey background
     }
@@ -4031,7 +3902,7 @@ bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const
 
 GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return m_wxwindow ? GTK_PIZZA(m_wxwindow)->bin_window : m_widget->window;
+    return m_wxwindow ? m_wxwindow->window : m_widget->window;
 }
 
 bool wxWindowGTK::SetFont( const wxFont &font )
@@ -4054,7 +3925,7 @@ void wxWindowGTK::DoCaptureMouse()
 
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
-        window = GTK_PIZZA(m_wxwindow)->bin_window;
+        window = m_wxwindow->window;
     else
         window = GetConnectWidget()->window;
 
@@ -4087,7 +3958,7 @@ void wxWindowGTK::DoReleaseMouse()
 
     GdkWindow *window = (GdkWindow*) NULL;
     if (m_wxwindow)
-        window = GTK_PIZZA(m_wxwindow)->bin_window;
+        window = m_wxwindow->window;
     else
         window = GetConnectWidget()->window;
 
@@ -4097,6 +3968,14 @@ void wxWindowGTK::DoReleaseMouse()
     gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
 }
 
+void wxWindowGTK::GTKReleaseMouseAndNotify()
+{
+    DoReleaseMouse();
+    wxMouseCaptureLostEvent evt(GetId());
+    evt.SetEventObject( this );
+    HandleWindowEvent( evt );
+}
+
 /* static */
 wxWindow *wxWindowBase::GetCapture()
 {
@@ -4108,27 +3987,15 @@ bool wxWindowGTK::IsRetained() const
     return false;
 }
 
-void wxWindowGTK::BlockScrollEvent()
-{
-    wxASSERT(!m_blockScrollEvent);
-    m_blockScrollEvent = true;
-}
-
-void wxWindowGTK::UnblockScrollEvent()
-{
-    wxASSERT(m_blockScrollEvent);
-    m_blockScrollEvent = false;
-}
-
 void wxWindowGTK::SetScrollbar(int orient,
                                int pos,
                                int thumbVisible,
                                int range,
                                bool WXUNUSED(update))
 {
-    wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
-    wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
-    wxCHECK_RET( m_wxwindow != m_widget, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
+    const int dir = ScrollDirFromOrient(orient);
+    GtkRange* const sb = m_scrollBar[dir];
+    wxCHECK_RET( sb, _T("this window is not scrollable") );
 
     if (range > 0)
     {
@@ -4141,71 +4008,65 @@ void wxWindowGTK::SetScrollbar(int orient,
         thumbVisible = 1;
     }
 
-    if (pos > range - thumbVisible)
-        pos = range - thumbVisible;
-    if (pos < 0)
-        pos = 0;
-    GtkAdjustment* adj = m_scrollBar[ScrollDirFromOrient(orient)]->adjustment;
+    GtkAdjustment * const adj = sb->adjustment;
     adj->step_increment = 1;
     adj->page_increment =
     adj->page_size = thumbVisible;
-    adj->upper = range;
-    SetScrollPos(orient, pos);
-    gtk_adjustment_changed(adj);
+    adj->value = pos;
+
+    g_signal_handlers_block_by_func(
+        sb, (void*)gtk_scrollbar_value_changed, this);
+
+    gtk_range_set_range(sb, 0, range);
+    m_scrollPos[dir] = sb->adjustment->value;
+
+    g_signal_handlers_unblock_by_func(
+        sb, (void*)gtk_scrollbar_value_changed, this);
 }
 
 void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 {
-    wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
-    wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
-    wxCHECK_RET( m_wxwindow != m_widget, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
+    const int dir = ScrollDirFromOrient(orient);
+    GtkRange * const sb = m_scrollBar[dir];
+    wxCHECK_RET( sb, _T("this window is not scrollable") );
 
     // This check is more than an optimization. Without it, the slider
     //   will not move smoothly while tracking when using wxScrollHelper.
     if (GetScrollPos(orient) != pos)
     {
-        const int dir = ScrollDirFromOrient(orient);
-        GtkAdjustment* adj = m_scrollBar[dir]->adjustment;
-        const int max = int(adj->upper - adj->page_size);
-        if (pos > max)
-            pos = max;
-        if (pos < 0)
-            pos = 0;
-        m_scrollPos[dir] = adj->value = pos;
-
-        // If a "value_changed" signal emission is not already in progress
-        if (!m_blockValueChanged[dir])
-        {
-            gtk_adjustment_value_changed(adj);
-        }
+        g_signal_handlers_block_by_func(
+            sb, (void*)gtk_scrollbar_value_changed, this);
+
+        gtk_range_set_value(sb, pos);
+        m_scrollPos[dir] = sb->adjustment->value;
+
+        g_signal_handlers_unblock_by_func(
+            sb, (void*)gtk_scrollbar_value_changed, this);
     }
 }
 
 int wxWindowGTK::GetScrollThumb(int orient) const
 {
-    wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
-    wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
-    wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
+    GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
+    wxCHECK_MSG( sb, 0, _T("this window is not scrollable") );
 
-    return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size);
+    return int(sb->adjustment->page_size);
 }
 
 int wxWindowGTK::GetScrollPos( int orient ) const
 {
-    wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
-    wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
-    wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
+    GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
+    wxCHECK_MSG( sb, 0, _T("this window is not scrollable") );
 
-    return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5);
+    return int(sb->adjustment->value + 0.5);
 }
 
 int wxWindowGTK::GetScrollRange( int orient ) const
 {
-    wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
-    wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
-    wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
+    GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
+    wxCHECK_MSG( sb, 0, _T("this window is not scrollable") );
 
-    return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper);
+    return int(sb->adjustment->upper);
 }
 
 // Determine if increment is the same as +/-x, allowing for some small
@@ -4219,8 +4080,6 @@ static inline bool IsScrollIncrement(double increment, double x)
 
 wxEventType wxWindowGTK::GetScrollEventType(GtkRange* range)
 {
-    DEBUG_MAIN_THREAD
-
     wxASSERT(range == m_scrollBar[0] || range == m_scrollBar[1]);
 
     const int barIndex = range == m_scrollBar[1];
@@ -4273,10 +4132,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
     m_clipPaintRegion = true;
 
-    if (GetLayoutDirection() == wxLayout_RightToLeft)
-        gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), dx, -dy );
-    else
-        gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
+    WX_PIZZA(m_wxwindow)->scroll(dx, dy);
 
     m_clipPaintRegion = false;
 
@@ -4316,8 +4172,11 @@ void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
             gtkstyle = GTK_SHADOW_OUT;
         else if (wxstyle & wxBORDER_SUNKEN)
             gtkstyle = GTK_SHADOW_IN;
+#if 0
+        // Now obsolete
         else if (wxstyle & wxBORDER_DOUBLE)
             gtkstyle = GTK_SHADOW_ETCHED_IN;
+#endif
         else //default
             gtkstyle = GTK_SHADOW_IN;
 
@@ -4371,13 +4230,10 @@ wxPoint wxGetMousePosition()
 
 }
 
-// Needed for implementing e.g. combobox on wxGTK within a modal dialog.
-void wxAddGrab(wxWindow* window)
+GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const
 {
-    gtk_grab_add( (GtkWidget*) window->GetHandle() );
-}
-
-void wxRemoveGrab(wxWindow* window)
-{
-    gtk_grab_remove( (GtkWidget*) window->GetHandle() );
+    GdkWindow* window = NULL;
+    if (m_wxwindow)
+        window = m_wxwindow->window;
+    return window;
 }