]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Invoke default action if dclick event after <ENTER> not handled in wxListBox, added...
[wxWidgets.git] / src / gtk / window.cpp
index 18a1c409d5aa85de255fb00a9910999e26c0e999..7e637c83b076ba1a89f5c960d55e7bde34be9352 100644 (file)
 #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)
 
@@ -212,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")
 
@@ -282,121 +258,6 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win)
     return (wxWindow *)NULL;
 }
 
-static void GetScrollbarWidth(GtkWidget* widget, int& w, int& h)
-{
-    GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(widget);
-    GtkScrolledWindowClass* scroll_class = GTK_SCROLLED_WINDOW_CLASS(GTK_OBJECT_GET_CLASS(scroll_window));
-    GtkRequisition scroll_req;
-
-    w = 0;
-    if (scroll_window->vscrollbar_visible)
-    {
-        scroll_req.width = 2;
-        scroll_req.height = 2;
-        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
-            (scroll_window->vscrollbar, &scroll_req );
-        w = scroll_req.width +
-            scroll_class->scrollbar_spacing;
-    }
-
-    h = 0;
-    if (scroll_window->hscrollbar_visible)
-    {
-        scroll_req.width = 2;
-        scroll_req.height = 2;
-        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
-            (scroll_window->hscrollbar, &scroll_req );
-        h = scroll_req.height +
-            scroll_class->scrollbar_spacing;
-    }
-}
-
-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
 //-----------------------------------------------------------------------------
@@ -419,70 +280,16 @@ void wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget),
 }
 }
 
-#if wxUSE_COMBOBOX
-
-extern "C" {
-static
-void wxgtk_combo_size_request_callback(GtkWidget * WXUNUSED(widget),
-                                       GtkRequisition *requisition,
-                                       wxWindow* 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;
-}
-}
-
-#endif // wxUSE_COMBOBOX
-
 //-----------------------------------------------------------------------------
 // "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())
     {
@@ -517,6 +324,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
 //-----------------------------------------------------------------------------
@@ -979,8 +846,6 @@ gtk_window_key_press_callback( GtkWidget *widget,
                                GdkEventKey *gdk_event,
                                wxWindow *win )
 {
-    DEBUG_MAIN_THREAD
-
     if (!win->m_hasVMT)
         return FALSE;
     if (g_blockEventsOnDrag)
@@ -999,7 +864,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
     {
@@ -1035,7 +900,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())
@@ -1094,13 +959,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 );
             }
         }
     }
@@ -1170,13 +1035,13 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(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 );
         }
     }
 }
@@ -1193,8 +1058,6 @@ gtk_window_key_release_callback( GtkWidget * WXUNUSED(widget),
                                  GdkEventKey *gdk_event,
                                  wxWindowGTK *win )
 {
-    DEBUG_MAIN_THREAD
-
     if (!win->m_hasVMT)
         return FALSE;
 
@@ -1243,7 +1106,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;
     }
 
@@ -1293,9 +1156,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();
@@ -1357,13 +1220,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)
@@ -1404,12 +1265,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
@@ -1452,10 +1313,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
@@ -1465,7 +1323,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)
     {
@@ -1722,8 +1579,6 @@ gtk_window_motion_notify_callback( GtkWidget * WXUNUSED(widget),
 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)
     {
@@ -1732,6 +1587,8 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
 
     wxMouseEvent event(wxEVT_MOUSEWHEEL);
     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)
@@ -1762,8 +1619,6 @@ 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);
 
@@ -1812,8 +1667,6 @@ 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);
 
@@ -1866,8 +1719,7 @@ wx_window_focus_callback(GtkWidget *widget,
                          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
@@ -1977,8 +1829,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;
 
@@ -2012,8 +1862,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
@@ -2034,15 +1882,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
@@ -2071,9 +1916,10 @@ size_allocate(GtkWidget*, GtkAllocation* alloc, wxWindow* win)
     int h = alloc->height;
     if (win->m_wxwindow)
     {
-        const int border = GTK_CONTAINER(win->m_wxwindow)->border_width;
-        w -= 2 * border;
-        h -= 2 * border;
+        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;
     }
@@ -2109,14 +1955,56 @@ gtk_window_grab_broken( GtkWidget*,
     {
         wxMouseCaptureLostEvent evt( win->GetId() );
         evt.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent( evt );
+        win->HandleWindowEvent( evt );
     }
     return false;
 }
 #endif
 
+//-----------------------------------------------------------------------------
+// "style_set"
+//-----------------------------------------------------------------------------
+
+static
+void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget),
+                               GtkStyle *previous_style,
+                               wxWindow* win )
+{
+    if (win && previous_style)
+    {
+        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
@@ -2143,16 +2031,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);
 }
 
 //-----------------------------------------------------------------------------
@@ -2224,7 +2110,6 @@ void wxWindowGTK::Init()
     m_noExpose = false;
     m_nativeSizeEvent = false;
 
-    m_hasScrolling = false;
     m_isScrolling = false;
     m_mouseButtonDown = false;
 
@@ -2276,6 +2161,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 ))
     {
@@ -2283,30 +2173,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);
@@ -2462,7 +2334,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
@@ -2474,9 +2346,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
@@ -2551,16 +2428,6 @@ void wxWindowGTK::PostCreation()
 #endif
     }
 
-#if wxUSE_COMBOBOX
-    if (GTK_IS_COMBO(m_widget))
-    {
-        GtkCombo *gcombo = GTK_COMBO(m_widget);
-
-        g_signal_connect (gcombo->entry, "size_request",
-                          G_CALLBACK (wxgtk_combo_size_request_callback),
-                          this);
-    } else
-#endif // wxUSE_COMBOBOX
 #ifdef GTK_IS_FILE_CHOOSER_BUTTON
     if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
     {
@@ -2613,6 +2480,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()
@@ -2626,9 +2497,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()
@@ -2682,9 +2553,9 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
 
     if (m_parent->m_wxwindow)
     {
-        GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
-        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;
@@ -2723,7 +2594,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         {
             wxSizeEvent event( wxSize(m_width,m_height), GetId() );
             event.SetEventObject( this );
-            GetEventHandler()->ProcessEvent( event );
+            HandleWindowEvent( event );
         }
     }
 }
@@ -2741,7 +2612,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;
     }
@@ -2780,7 +2651,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() );
 
@@ -2830,18 +2701,27 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
 
     if (m_wxwindow)
     {
-        int dw = 0;
-        int dh = 0;
-
-        if (m_hasScrolling)
-            GetScrollbarWidth(m_widget, dw, dh);
+        // if window is scrollable, account for scrollbars
+        for (int i = 0; i < 2 && m_scrollBar[i]; i++)
+        {
+            GtkRequisition req;
+            GtkAdjustment* adj = gtk_range_get_adjustment(m_scrollBar[i]);
+            // if scrollbar enabled
+            if (adj->upper > adj->page_size)
+            {
+                gtk_widget_size_request(GTK_WIDGET(m_scrollBar[i]), &req);
+                if (i == ScrollDir_Horz)
+                    h -= req.height;
+                else
+                    w -= req.width;
+            }
+        }
 
-        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);
+        w -= 2 * border_x;
+        h -= 2 * border_y;
 
-        w -= dw;
-        h -= dh;
         if (w < 0)
             w = 0;
         if (h < 0)
@@ -2860,16 +2740,16 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
     int dy = 0;
     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;
 
@@ -2899,7 +2779,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;
 
@@ -2936,7 +2816,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;
 
@@ -2973,22 +2853,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;
@@ -3336,11 +3213,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;
@@ -3519,7 +3396,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;
 
@@ -3580,7 +3457,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
 
     if (m_wxwindow)
     {
-        if (!GTK_PIZZA(m_wxwindow)->bin_window) return;
+        if (m_wxwindow->window == NULL) return;
 
         GdkRectangle gdk_rect,
                     *p;
@@ -3600,7 +3477,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
             p = NULL;
         }
 
-        gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
+        gdk_window_invalidate_rect(m_wxwindow->window, p, true);
     }
 }
 
@@ -3617,8 +3494,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 );
 
@@ -3666,8 +3543,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)
@@ -3685,9 +3561,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
@@ -3707,7 +3580,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,
@@ -3724,19 +3597,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;
 
@@ -3909,6 +3790,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
@@ -3924,7 +3807,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
         GdkWindow *window;
         if ( m_wxwindow )
         {
-            window = GTK_PIZZA(m_wxwindow)->bin_window;
+            window = m_wxwindow->window;
         }
         else
         {
@@ -3997,7 +3880,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 )
@@ -4020,7 +3903,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;
 
@@ -4053,7 +3936,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;
 
@@ -4068,7 +3951,7 @@ void wxWindowGTK::GTKReleaseMouseAndNotify()
     DoReleaseMouse();
     wxMouseCaptureLostEvent evt(GetId());
     evt.SetEventObject( this );
-    GetEventHandler()->ProcessEvent( evt );
+    HandleWindowEvent( evt );
 }
 
 /* static */
@@ -4092,11 +3975,7 @@ void wxWindowGTK::SetScrollbar(int orient,
     GtkRange* const sb = m_scrollBar[dir];
     wxCHECK_RET( sb, _T("this window is not scrollable") );
 
-    if (range > 0)
-    {
-        m_hasScrolling = true;
-    }
-    else
+    if (range <= 0)
     {
         // GtkRange requires upper > lower
         range =
@@ -4175,8 +4054,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];
@@ -4229,10 +4106,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;
 
@@ -4330,13 +4204,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;
 }