]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
guard XTI
[wxWidgets.git] / src / gtk / window.cpp
index 6834a221eaa16918a478de1a1c600c81e3a411c1..4178eddb5729d9c1612df273c082c4667cc8caa4 100644 (file)
 
 #include "wx/gtk/private.h"
 #include "wx/gtk/private/win_gtk.h"
+#include "wx/gtk/private/event.h"
+using namespace wxGTKImpl;
 
+#ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
+#include "wx/x11/private/wrapxkb.h"
+#else
+typedef guint KeySym;
+#endif
 
 #include <gdk/gdkkeysyms.h>
 #if GTK_CHECK_VERSION(3,0,0)
 #include <gdk/gdkkeysyms-compat.h>
 #endif
 
-#if !GTK_CHECK_VERSION(2,10,0)
-    // GTK+ can reliably detect Meta key state only since 2.10 when
-    // GDK_META_MASK was introduced -- there wasn't any way to detect it
-    // in older versions. wxGTK used GDK_MOD2_MASK for this purpose, but
-    // GDK_MOD2_MASK is documented as:
-    //
-    //     the fifth modifier key (it depends on the modifier mapping of the X
-    //     server which key is interpreted as this modifier)
-    //
-    // In other words, it isn't guaranteed to map to Meta. This is a real
-    // problem: it is common to map NumLock to it (in fact, it's an exception
-    // if the X server _doesn't_ use it for NumLock).  So the old code caused
-    // wxKeyEvent::MetaDown() to always return true as long as NumLock was on
-    // on many systems, which broke all applications using
-    // wxKeyEvent::GetModifiers() to check modifiers state (see e.g.  here:
-    // http://tinyurl.com/56lsk2).
-    //
-    // Because of this, it's better to not detect Meta key state at all than
-    // to detect it incorrectly. Hence the following #define, which causes
-    // m_metaDown to be always set to false.
-    #define GDK_META_MASK 0
-#endif
+// gdk_window_set_composited() is only supported since 2.12
+#define wxGTK_VERSION_REQUIRED_FOR_COMPOSITING 2,12,0
+#define wxGTK_HAS_COMPOSITING_SUPPORT GTK_CHECK_VERSION(2,12,0)
 
 //-----------------------------------------------------------------------------
 // documentation on internals
@@ -233,51 +221,6 @@ int          g_lastButtonNumber = 0;
 // the trace mask used for the focus debugging messages
 #define TRACE_FOCUS wxT("focus")
 
-//-----------------------------------------------------------------------------
-// missing gdk functions
-//-----------------------------------------------------------------------------
-
-void
-gdk_window_warp_pointer (GdkWindow      *window,
-                         gint            x,
-                         gint            y)
-{
-  if (!window)
-    window = gdk_get_default_root_window();
-
-  if (!GDK_WINDOW_DESTROYED(window))
-  {
-      XWarpPointer (GDK_WINDOW_XDISPLAY(window),
-                    None,              /* not source window -> move from anywhere */
-                    GDK_WINDOW_XID(window),  /* dest window */
-                    0, 0, 0, 0,        /* not source window -> move from anywhere */
-                    x, y );
-  }
-}
-
-
-//-----------------------------------------------------------------------------
-// "size_request" of m_widget
-//-----------------------------------------------------------------------------
-
-extern "C" {
-static void
-wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget),
-                                   GtkRequisition *requisition,
-                                   wxWindow * win)
-{
-    int w, h;
-    win->GetSize( &w, &h );
-    if (w < 2)
-        w = 2;
-    if (h < 2)
-        h = 2;
-
-    requisition->height = h;
-    requisition->width = w;
-}
-}
-
 //-----------------------------------------------------------------------------
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
@@ -360,7 +303,7 @@ expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win)
 
 extern "C" {
 static void
-parent_set(GtkWidget* widget, GtkObject* old_parent, wxWindow* win)
+parent_set(GtkWidget* widget, GtkWidget* old_parent, wxWindow* win)
 {
     if (old_parent)
     {
@@ -381,18 +324,6 @@ parent_set(GtkWidget* widget, GtkObject* old_parent, wxWindow* win)
 // "key_press_event" from any window
 //-----------------------------------------------------------------------------
 
-// These are used when transforming Ctrl-alpha to ascii values 1-26
-inline bool wxIsLowerChar(int code)
-{
-    return (code >= 'a' && code <= 'z' );
-}
-
-inline bool wxIsUpperChar(int code)
-{
-    return (code >= 'A' && code <= 'Z' );
-}
-
-
 // set WXTRACE to this to see the key event codes on the console
 #define TRACE_KEYS  wxT("keyevent")
 
@@ -779,6 +710,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
                 keysym = (KeySym)gdk_event->string[0];
             }
 
+#ifdef GDK_WINDOWING_X11
             // we want to always get the same key code when the same key is
             // pressed regardless of the state of the modifiers, i.e. on a
             // standard US keyboard pressing '5' or '%' ('5' key with
@@ -792,11 +724,18 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
 
             wxLogTrace(TRACE_KEYS, wxT("\t-> keycode %d"), keycode);
 
+#ifdef HAVE_X11_XKBLIB_H
+            KeySym keysymNormalized = XkbKeycodeToKeysym(dpy, keycode, 0, 0);
+#else
             KeySym keysymNormalized = XKeycodeToKeysym(dpy, keycode, 0);
+#endif
 
             // use the normalized, i.e. lower register, keysym if we've
             // got one
             key_code = keysymNormalized ? keysymNormalized : keysym;
+#else
+            key_code = keysym;
+#endif
 
             // as explained above, we want to have lower register key codes
             // normally but for the letter keys we want to have the upper ones
@@ -874,38 +813,73 @@ struct wxGtkIMData
 namespace
 {
 
-// Send wxEVT_CHAR_HOOK event to the parent of the window and if it wasn't
-// processed, send wxEVT_CHAR to the window itself. Return true if either of
-// them was handled.
-bool
-SendCharHookAndCharEvents(const wxKeyEvent& event, wxWindow *win)
+// Send wxEVT_CHAR_HOOK event to the parent of the window and return true only
+// if it was processed (and not skipped).
+bool SendCharHookEvent(const wxKeyEvent& event, wxWindow *win)
 {
-    // wxEVT_CHAR_HOOK must be sent to the top level parent window to allow it
+    // wxEVT_CHAR_HOOK must be sent to allow the parent windows (e.g. a dialog
+    // which typically closes when Esc key is pressed in any of its controls)
     // to handle key events in all of its children unless the mouse is captured
     // in which case we consider that the keyboard should be "captured" too.
     if ( !g_captureWindow )
     {
-        wxWindow * const parent = wxGetTopLevelParent(win);
-        if ( parent )
-        {
-            // We need to make a copy of the event object because it is
-            // modified while it's handled, notably its WasProcessed() flag
-            // is set after it had been processed once.
-            wxKeyEvent eventCharHook(event);
-            eventCharHook.SetEventType(wxEVT_CHAR_HOOK);
-            if ( parent->HandleWindowEvent(eventCharHook) )
-                return true;
-        }
+        wxKeyEvent eventCharHook(wxEVT_CHAR_HOOK, event);
+        if ( win->HandleWindowEvent(eventCharHook)
+                && !event.IsNextEventAllowed() )
+            return true;
     }
 
-    // As above, make a copy of the event first.
-    wxKeyEvent eventChar(event);
-    eventChar.SetEventType(wxEVT_CHAR);
-    return win->HandleWindowEvent(eventChar);
+    return false;
+}
+
+// Adjust wxEVT_CHAR event key code fields. This function takes care of two
+// conventions:
+// (a) Ctrl-letter key presses generate key codes in range 1..26
+// (b) Unicode key codes are same as key codes for the codes in 1..255 range
+void AdjustCharEventKeyCodes(wxKeyEvent& event)
+{
+    const int code = event.m_keyCode;
+
+    // Check for (a) above.
+    if ( event.ControlDown() )
+    {
+        // We intentionally don't use isupper/lower() here, we really need
+        // ASCII letters only as it doesn't make sense to translate any other
+        // ones into this range which has only 26 slots.
+        if ( code >= 'a' && code <= 'z' )
+            event.m_keyCode = code - 'a' + 1;
+        else if ( code >= 'A' && code <= 'Z' )
+            event.m_keyCode = code - 'A' + 1;
+
+#if wxUSE_UNICODE
+        // Adjust the Unicode equivalent in the same way too.
+        if ( event.m_keyCode != code )
+            event.m_uniChar = event.m_keyCode;
+#endif // wxUSE_UNICODE
+    }
+
+#if wxUSE_UNICODE
+    // Check for (b) from above.
+    //
+    // FIXME: Should we do it for key codes up to 255?
+    if ( !event.m_uniChar && code < WXK_DELETE )
+        event.m_uniChar = code;
+#endif // wxUSE_UNICODE
 }
 
 } // anonymous namespace
 
+// If a widget does not handle a key or mouse event, GTK+ sends it up the
+// parent chain until it is handled. These events are not supposed to propagate
+// in wxWidgets, so this code avoids handling them in any parent wxWindow,
+// while still allowing the event to propagate so things like native keyboard
+// navigation will work.
+#define wxPROCESS_EVENT_ONCE(EventType, event) \
+    static EventType eventPrev; \
+    if (memcmp(&eventPrev, event, sizeof(EventType)) == 0) \
+        return false; \
+    eventPrev = *event
+
 extern "C" {
 static gboolean
 gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
@@ -917,12 +891,21 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
     if (g_blockEventsOnDrag)
         return FALSE;
 
+    wxPROCESS_EVENT_ONCE(GdkEventKey, gdk_event);
+
     wxKeyEvent event( wxEVT_KEY_DOWN );
     bool ret = false;
     bool return_after_IM = false;
 
     if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
     {
+        // Send the CHAR_HOOK event first
+        if ( SendCharHookEvent(event, win) )
+        {
+            // Don't do anything at all with this event any more.
+            return TRUE;
+        }
+
         // Emit KEY_DOWN event
         ret = win->HandleWindowEvent( event );
     }
@@ -940,7 +923,8 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
         // docs, if IM filter returns true, no further processing should be done.
         // we should send the key_down event anyway.
-        bool intercepted_by_IM = gtk_im_context_filter_keypress(win->m_imData->context, gdk_event);
+        bool intercepted_by_IM =
+            gtk_im_context_filter_keypress(win->m_imData->context, gdk_event) != 0;
         win->m_imData->lastKeyEvent = NULL;
         if (intercepted_by_IM)
         {
@@ -1006,25 +990,15 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
 
         if ( key_code )
         {
+            wxKeyEvent eventChar(wxEVT_CHAR, event);
+
             wxLogTrace(TRACE_KEYS, wxT("Char event: %ld"), key_code);
 
-            event.m_keyCode = key_code;
+            eventChar.m_keyCode = key_code;
 
-            // To conform to the docs we need to translate Ctrl-alpha
-            // characters to values in the range 1-26.
-            if ( event.ControlDown() &&
-                 ( wxIsLowerChar(key_code) || wxIsUpperChar(key_code) ))
-            {
-                if ( wxIsLowerChar(key_code) )
-                    event.m_keyCode = key_code - 'a' + 1;
-                if ( wxIsUpperChar(key_code) )
-                    event.m_keyCode = key_code - 'A' + 1;
-#if wxUSE_UNICODE
-                event.m_uniChar = event.m_keyCode;
-#endif
-            }
+            AdjustCharEventKeyCodes(eventChar);
 
-            ret = SendCharHookAndCharEvents(event, win);
+            ret = win->HandleWindowEvent(eventChar);
         }
     }
 
@@ -1038,7 +1012,7 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context),
                         const gchar  *str,
                         wxWindow     *window)
 {
-    wxKeyEvent event( wxEVT_KEY_DOWN );
+    wxKeyEvent event( wxEVT_CHAR );
 
     // take modifiers, cursor position, timestamp etc. from the last
     // key_press_event that was fed into Input Method:
@@ -1067,23 +1041,9 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context),
         event.m_keyCode = (char)*pstr;
 #endif  // wxUSE_UNICODE
 
-        // To conform to the docs we need to translate Ctrl-alpha
-        // characters to values in the range 1-26.
-        if ( event.ControlDown() &&
-             ( wxIsLowerChar(*pstr) || wxIsUpperChar(*pstr) ))
-        {
-            if ( wxIsLowerChar(*pstr) )
-                event.m_keyCode = *pstr - 'a' + 1;
-            if ( wxIsUpperChar(*pstr) )
-                event.m_keyCode = *pstr - 'A' + 1;
-
-            event.m_keyCode = *pstr - 'a' + 1;
-#if wxUSE_UNICODE
-            event.m_uniChar = event.m_keyCode;
-#endif
-        }
+        AdjustCharEventKeyCodes(event);
 
-        SendCharHookAndCharEvents(event, window);
+        window->HandleWindowEvent(event);
     }
 }
 }
@@ -1105,6 +1065,8 @@ gtk_window_key_release_callback( GtkWidget * WXUNUSED(widget),
     if (g_blockEventsOnDrag)
         return FALSE;
 
+    wxPROCESS_EVENT_ONCE(GdkEventKey, gdk_event);
+
     wxKeyEvent event( wxEVT_KEY_UP );
     if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
     {
@@ -1124,44 +1086,6 @@ gtk_window_key_release_callback( GtkWidget * WXUNUSED(widget),
 // mouse event processing helpers
 // ----------------------------------------------------------------------------
 
-// init wxMouseEvent with the info from GdkEventXXX struct
-template<typename T> void InitMouseEvent(wxWindowGTK *win,
-                                         wxMouseEvent& event,
-                                         T *gdk_event)
-{
-    event.SetTimestamp( gdk_event->time );
-    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0;
-    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
-    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
-    event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0;
-    event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK) != 0;
-    event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK) != 0;
-    event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK) != 0;
-
-    // In gdk/win32 VK_XBUTTON1 is translated to GDK_BUTTON4_MASK
-    // and VK_XBUTTON2 to GDK_BUTTON5_MASK. In x11/gdk buttons 4/5
-    // are wheel rotation and buttons 8/9 don't change the state.
-    event.m_aux1Down = (gdk_event->state & GDK_BUTTON4_MASK) != 0;
-    event.m_aux2Down = (gdk_event->state & GDK_BUTTON5_MASK) != 0;
-
-    wxPoint pt = win->GetClientAreaOrigin();
-    event.m_x = (wxCoord)gdk_event->x - pt.x;
-    event.m_y = (wxCoord)gdk_event->y - pt.y;
-
-    if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft))
-    {
-        // origin in the upper right corner
-        GtkAllocation a;
-        gtk_widget_get_allocation(win->m_wxwindow, &a);
-        int window_width = a.width;
-        event.m_x = window_width - event.m_x;
-    }
-
-    event.SetEventObject( win );
-    event.SetId( win->GetId() );
-    event.SetTimestamp( gdk_event->time );
-}
-
 static void AdjustEventButtonState(wxMouseEvent& event)
 {
     // GDK reports the old state of the button for a button press event, but
@@ -1208,7 +1132,7 @@ static void AdjustEventButtonState(wxMouseEvent& event)
     }
 }
 
-// find the window to send the mouse event too
+// find the window to send the mouse event to
 static
 wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
 {
@@ -1225,7 +1149,7 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
     wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
     while (node)
     {
-        wxWindowGTK *child = node->GetData();
+        wxWindow* child = static_cast<wxWindow*>(node->GetData());
 
         node = node->GetNext();
         if (!child->IsShown())
@@ -1258,6 +1182,7 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
         else
         {
             if ((child->m_wxwindow == NULL) &&
+                win->IsClientAreaChild(child) &&
                 (child->m_x <= xx) &&
                 (child->m_y <= yy) &&
                 (child->m_x+child->m_width  >= xx) &&
@@ -1337,6 +1262,8 @@ gtk_window_button_press_callback( GtkWidget *widget,
                                   GdkEventButton *gdk_event,
                                   wxWindowGTK *win )
 {
+    wxPROCESS_EVENT_ONCE(GdkEventButton, gdk_event);
+
     wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     g_lastButtonNumber = gdk_event->button;
@@ -1534,6 +1461,8 @@ gtk_window_button_release_callback( GtkWidget *WXUNUSED(widget),
                                     GdkEventButton *gdk_event,
                                     wxWindowGTK *win )
 {
+    wxPROCESS_EVENT_ONCE(GdkEventButton, gdk_event);
+
     wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     g_lastButtonNumber = 0;
@@ -1597,6 +1526,8 @@ gtk_window_motion_notify_callback( GtkWidget * WXUNUSED(widget),
                                    GdkEventMotion *gdk_event,
                                    wxWindowGTK *win )
 {
+    wxPROCESS_EVENT_ONCE(GdkEventMotion, gdk_event);
+
     wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
 
     if (gdk_event->is_hint)
@@ -1693,22 +1624,43 @@ window_scroll_event_hscrollbar(GtkWidget*, GdkEventScroll* gdk_event, wxWindow*
 static gboolean
 window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
 {
-    if (gdk_event->direction != GDK_SCROLL_UP &&
-        gdk_event->direction != GDK_SCROLL_DOWN)
-    {
-        return false;
-    }
-
     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)
-        event.m_wheelRotation = 120;
-    else
-        event.m_wheelRotation = -120;
+
+    // Determine the scroll direction.
+    switch (gdk_event->direction)
+    {
+        case GDK_SCROLL_UP:
+        case GDK_SCROLL_RIGHT:
+            event.m_wheelRotation = 120;
+            break;
+
+        case GDK_SCROLL_DOWN:
+        case GDK_SCROLL_LEFT:
+            event.m_wheelRotation = -120;
+            break;
+
+        default:
+            return false;  // Unknown/unhandled direction
+    }
+
+    // And the scroll axis.
+    switch (gdk_event->direction)
+    {
+        case GDK_SCROLL_UP:
+        case GDK_SCROLL_DOWN:
+            event.m_wheelAxis = wxMOUSE_WHEEL_VERTICAL;
+            break;
+
+        case GDK_SCROLL_LEFT:
+        case GDK_SCROLL_RIGHT:
+            event.m_wheelAxis = wxMOUSE_WHEEL_HORIZONTAL;
+            break;
+    }
 
     if (win->GTKProcessEvent(event))
       return TRUE;
@@ -1937,29 +1889,19 @@ gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* w
 //-----------------------------------------------------------------------------
 
 static void
-gtk_window_realized_callback(GtkWidget* widget, wxWindow* win)
+gtk_window_realized_callback(GtkWidget* WXUNUSED(widget), wxWindowGTK* win)
 {
-    if (win->m_imData)
-    {
-        gtk_im_context_set_client_window( win->m_imData->context,
-            win->m_wxwindow ? win->GTKGetDrawingWindow() : gtk_widget_get_window(widget));
-    }
-
-    // We cannot set colours and fonts before the widget
-    // been realized, so we do this directly after realization
-    // or otherwise in idle time
-
-    if (win->m_needsStyleChange)
-    {
-        win->SetBackgroundStyle(win->GetBackgroundStyle());
-        win->m_needsStyleChange = false;
-    }
+    win->GTKHandleRealized();
+}
 
-    wxWindowCreateEvent event( win );
-    event.SetEventObject( win );
-    win->GTKProcessEvent( event );
+//-----------------------------------------------------------------------------
+// "unrealize" from m_wxwindow
+//-----------------------------------------------------------------------------
 
-    win->GTKUpdateCursor(true, false);
+static void unrealize(GtkWidget*, wxWindowGTK* win)
+{
+    if (win->m_imData)
+        gtk_im_context_set_client_window(win->m_imData->context, NULL);
 }
 
 //-----------------------------------------------------------------------------
@@ -2031,15 +1973,71 @@ void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget),
 {
     if (win && previous_style)
     {
-        wxSysColourChangedEvent event;
-        event.SetEventObject(win);
-
-        win->GTKProcessEvent( event );
+        if (win->IsTopLevel())
+        {
+            wxSysColourChangedEvent event;
+            event.SetEventObject(win);
+            win->GTKProcessEvent(event);
+        }
+        else
+        {
+            // Border width could change, which will change client size.
+            // Make sure size event occurs for this
+            win->m_oldClientWidth = 0;
+        }
     }
 }
 
 } // extern "C"
 
+void wxWindowGTK::GTKHandleRealized()
+{
+    if (m_imData)
+    {
+        gtk_im_context_set_client_window
+        (
+            m_imData->context,
+            m_wxwindow ? GTKGetDrawingWindow()
+                       : gtk_widget_get_window(m_widget)
+        );
+    }
+
+    // Use composited window if background is transparent, if supported.
+    if (m_backgroundStyle == wxBG_STYLE_TRANSPARENT)
+    {
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+        if (IsTransparentBackgroundSupported())
+        {
+            GdkWindow* const window = GTKGetDrawingWindow();
+            if (window)
+                gdk_window_set_composited(window, true);
+        }
+        else
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+        {
+            // We revert to erase mode if transparency is not supported
+            m_backgroundStyle = wxBG_STYLE_ERASE;
+        }
+    }
+
+
+    // We cannot set colours and fonts before the widget
+    // been realized, so we do this directly after realization
+    // or otherwise in idle time
+
+    if (m_needsStyleChange)
+    {
+        SetBackgroundStyle(GetBackgroundStyle());
+        m_needsStyleChange = false;
+    }
+
+    wxWindowCreateEvent event(static_cast<wxWindow*>(this));
+    event.SetEventObject( this );
+    GTKProcessEvent( event );
+
+    GTKUpdateCursor(true, false);
+}
+
 // ----------------------------------------------------------------------------
 // this wxWindowBase function is implemented here (in platform-specific file)
 // because it is static and so couldn't be made virtual
@@ -2047,6 +2045,13 @@ void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget),
 
 wxWindow *wxWindowBase::DoFindFocus()
 {
+    // For compatibility with wxMSW, pretend that showing a popup menu doesn't
+    // change the focus and that it remains on the window showing it, even
+    // though the real focus does change in GTK.
+    extern wxMenu *wxCurrentPopupMenu;
+    if ( wxCurrentPopupMenu )
+        return wxCurrentPopupMenu->GetInvokingWindow();
+
     wxWindowGTK *focus = gs_pendingFocus ? gs_pendingFocus : gs_currentFocus;
     // the cast is necessary when we compile in wxUniversal mode
     return static_cast<wxWindow*>(focus);
@@ -2062,9 +2067,8 @@ void wxWindowGTK::AddChildGTK(wxWindowGTK* child)
     child->m_x += pizza->m_scroll_x;
     child->m_y += pizza->m_scroll_y;
 
-    gtk_widget_set_size_request(
-        child->m_widget, child->m_width, child->m_height);
-    pizza->put(child->m_widget, child->m_x, child->m_y);
+    pizza->put(child->m_widget,
+        child->m_x, child->m_y, child->m_width, child->m_height);
 }
 
 //-----------------------------------------------------------------------------
@@ -2320,6 +2324,7 @@ wxWindowGTK::~wxWindowGTK()
 
     // delete before the widgets to avoid a crash on solaris
     delete m_imData;
+    m_imData = NULL;
 
     // avoid problem with GTK+ 2.18 where a frozen window causes the whole
     // TLW to be frozen, and if the window is then destroyed, nothing ever
@@ -2352,8 +2357,11 @@ bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const w
     m_width = WidthDefault(size.x) ;
     m_height = HeightDefault(size.y);
 
-    m_x = (int)pos.x;
-    m_y = (int)pos.y;
+    if (pos != wxDefaultPosition)
+    {
+        m_x = pos.x;
+        m_y = pos.y;
+    }
 
     return true;
 }
@@ -2362,6 +2370,21 @@ void wxWindowGTK::PostCreation()
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
 
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+    // Set RGBA visual as soon as possible to minimize the possibility that
+    // somebody uses the wrong one.
+    if ( m_backgroundStyle == wxBG_STYLE_TRANSPARENT &&
+            IsTransparentBackgroundSupported() )
+    {
+        GdkScreen *screen = gtk_widget_get_screen (m_widget);
+
+        GdkColormap *rgba_colormap = gdk_screen_get_rgba_colormap (screen);
+
+        if (rgba_colormap)
+            gtk_widget_set_colormap(m_widget, rgba_colormap);
+    }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+
     if (m_wxwindow)
     {
         if (!m_noExpose)
@@ -2383,6 +2406,7 @@ void wxWindowGTK::PostCreation()
 
         g_signal_connect (m_imData->context, "commit",
                           G_CALLBACK (gtk_wxwindow_commit_cb), this);
+        g_signal_connect(m_wxwindow, "unrealize", G_CALLBACK(unrealize), this);
     }
 
     // focus handling
@@ -2422,10 +2446,18 @@ void wxWindowGTK::PostCreation()
 
     ConnectWidget( connect_widget );
 
-    /* We cannot set colours, fonts and cursors before the widget has
-       been realized, so we do this directly after realization */
-    g_signal_connect (connect_widget, "realize",
-                      G_CALLBACK (gtk_window_realized_callback), this);
+    // We cannot set colours, fonts and cursors before the widget has been
+    // realized, so we do this directly after realization -- unless the widget
+    // was in fact realized already.
+    if ( gtk_widget_get_realized(connect_widget) )
+    {
+        gtk_window_realized_callback(connect_widget, this);
+    }
+    else
+    {
+        g_signal_connect (connect_widget, "realize",
+                          G_CALLBACK (gtk_window_realized_callback), this);
+    }
 
     if (!IsTopLevel())
     {
@@ -2451,16 +2483,8 @@ void wxWindowGTK::PostCreation()
     }
 #endif // GTK+ >= 2.8
 
-    if ( GTKShouldConnectSizeRequest() )
-    {
-        // This is needed if we want to add our windows into native
-        // GTK controls, such as the toolbar. With this callback, the
-        // toolbar gets to know the correct size (the one set by the
-        // programmer). Sadly, it misbehaves for wxComboBox.
-        g_signal_connect (m_widget, "size_request",
-                          G_CALLBACK (wxgtk_window_size_request_callback),
-                          this);
-    }
+    if (!WX_IS_PIZZA(gtk_widget_get_parent(m_widget)) && !GTK_IS_WINDOW(m_widget))
+        gtk_widget_set_size_request(m_widget, m_width, m_height);
 
     InheritAttributes();
 
@@ -2474,7 +2498,8 @@ void wxWindowGTK::PostCreation()
         gtk_widget_show( m_widget );
 }
 
-unsigned long wxWindowGTK::GTKConnectWidget(const char *signal, void (*callback)())
+unsigned long
+wxWindowGTK::GTKConnectWidget(const char *signal, wxGTKCallback callback)
 {
     return g_signal_connect(m_widget, signal, callback, this);
 }
@@ -2508,7 +2533,7 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
     g_signal_connect (widget, "leave_notify_event",
                       G_CALLBACK (gtk_window_leave_callback), this);
 
-    if (IsTopLevel() && m_wxwindow)
+    if (m_wxwindow && (IsTopLevel() || HasFlag(wxBORDER_RAISED | wxBORDER_SUNKEN | wxBORDER_THEME)))
         g_signal_connect (m_wxwindow, "style_set",
                               G_CALLBACK (gtk_window_style_set_callback), this);
 }
@@ -2520,14 +2545,46 @@ bool wxWindowGTK::Destroy()
     return wxWindowBase::Destroy();
 }
 
+static GSList* gs_queueResizeList;
+
+extern "C" {
+static gboolean queue_resize(void*)
+{
+    gdk_threads_enter();
+    for (GSList* p = gs_queueResizeList; p; p = p->next)
+    {
+        if (p->data)
+        {
+            gtk_widget_queue_resize(GTK_WIDGET(p->data));
+            g_object_remove_weak_pointer(G_OBJECT(p->data), &p->data);
+        }
+    }
+    g_slist_free(gs_queueResizeList);
+    gs_queueResizeList = NULL;
+    gdk_threads_leave();
+    return false;
+}
+}
+
 void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
 {
     gtk_widget_set_size_request(m_widget, width, height);
+    GtkWidget* parent = gtk_widget_get_parent(m_widget);
+    if (WX_IS_PIZZA(parent))
+        WX_PIZZA(parent)->move(m_widget, x, y, width, height);
 
-    // inform the parent to perform the move
-    wxASSERT_MSG(m_parent && m_parent->m_wxwindow,
-                 "the parent window has no client area?");
-    WX_PIZZA(m_parent->m_wxwindow)->move(m_widget, x, y);
+    // With GTK3, gtk_widget_queue_resize() is ignored while a size-allocate
+    // is in progress. This situation is common in wxWidgets, since
+    // size-allocate can generate wxSizeEvent and size event handlers often
+    // call SetSize(), directly or indirectly. Work around this by deferring
+    // the queue-resize until after size-allocate processing is finished.
+    if (g_slist_find(gs_queueResizeList, m_widget) == NULL)
+    {
+        if (gs_queueResizeList == NULL)
+            g_idle_add_full(GTK_PRIORITY_RESIZE, queue_resize, NULL, NULL);
+        gs_queueResizeList = g_slist_prepend(gs_queueResizeList, m_widget);
+        g_object_add_weak_pointer(G_OBJECT(m_widget), &gs_queueResizeList->data);
+    }
 }
 
 void wxWindowGTK::ConstrainSize()
@@ -2549,16 +2606,24 @@ void wxWindowGTK::ConstrainSize()
 
 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") );
+    wxCHECK_RET(m_widget, "invalid window");
 
-    int currentX, currentY;
-    GetPosition(&currentX, &currentY);
-    if (x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
-        x = currentX;
-    if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
-        y = currentY;
-    AdjustForParentClientOrigin(x, y, sizeFlags);
+    int scrollX = 0, scrollY = 0;
+    GtkWidget* parent = gtk_widget_get_parent(m_widget);
+    if (WX_IS_PIZZA(parent))
+    {
+        wxPizza* pizza = WX_PIZZA(parent);
+        scrollX = pizza->m_scroll_x;
+        scrollY = pizza->m_scroll_y;
+    }
+    if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+        x += scrollX;
+    else
+        x = m_x;
+    if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+        y += scrollY;
+    else
+        y = m_y;
 
     // calculate the best size if we should auto size the window
     if ( ((sizeFlags & wxSIZE_AUTO_WIDTH) && width == -1) ||
@@ -2571,22 +2636,18 @@ 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)
-        m_height = height;
+    if (width == -1)
+        width = m_width;
+    if (height == -1)
+        height = m_height;
 
-    if (m_parent->m_wxwindow)
+    const bool sizeChange = m_width != width || m_height != height;
+    if (sizeChange || m_x != x || m_y != y)
     {
-        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;
-        int top_border = 0;
-        int bottom_border = 0;
+        m_x = x;
+        m_y = y;
+        m_width = width;
+        m_height = height;
 
         /* the default button has a border around it */
         if (gtk_widget_get_can_default(m_widget))
@@ -2595,36 +2656,23 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
             gtk_widget_style_get( m_widget, "default_border", &default_border, NULL );
             if (default_border)
             {
-                left_border += default_border->left;
-                right_border += default_border->right;
-                top_border += default_border->top;
-                bottom_border += default_border->bottom;
+                x -= default_border->left;
+                y -= default_border->top;
+                width += default_border->left + default_border->right;
+                height += default_border->top + default_border->bottom;
                 gtk_border_free( default_border );
             }
         }
 
-        DoMoveWindow( m_x - left_border,
-                      m_y - top_border,
-                      m_width+left_border+right_border,
-                      m_height+top_border+bottom_border );
+        DoMoveWindow(x, y, width, height);
     }
 
-    if (m_width != oldSize.x || m_height != oldSize.y)
+    if ((sizeChange && !m_nativeSizeEvent) || (sizeFlags & wxSIZE_FORCE_EVENT))
     {
         // update these variables to keep size_allocate handler
         // from sending another size event for this change
         GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
 
-        gtk_widget_queue_resize(m_widget);
-        if (!m_nativeSizeEvent)
-        {
-            wxSizeEvent event( wxSize(m_width,m_height), GetId() );
-            event.SetEventObject( this );
-            HandleWindowEvent( event );
-        }
-    } else
-    if (sizeFlags & wxSIZE_FORCE_EVENT)
-    {
         wxSizeEvent event( wxSize(m_width,m_height), GetId() );
         event.SetEventObject( this );
         HandleWindowEvent( event );
@@ -2666,21 +2714,11 @@ void wxWindowGTK::OnInternalIdle()
         RealizeTabOrder();
     }
 
-    // Update style if the window was not yet realized when
-    // SetBackgroundStyle() was called
-    if (m_needsStyleChange)
-    {
-        SetBackgroundStyle(GetBackgroundStyle());
-        m_needsStyleChange = false;
-    }
-
     wxWindowBase::OnInternalIdle();
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
 {
-    wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
     if (width) (*width) = m_width;
     if (height) (*height) = m_height;
 }
@@ -2775,39 +2813,17 @@ wxSize wxWindowGTK::DoGetBorderSize() const
 
 void wxWindowGTK::DoGetPosition( int *x, int *y ) const
 {
-    wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
     int dx = 0;
     int dy = 0;
-    if (!IsTopLevel() && m_parent && m_parent->m_wxwindow)
+    GtkWidget* parent = NULL;
+    if (m_widget)
+        parent = gtk_widget_get_parent(m_widget);
+    if (WX_IS_PIZZA(parent))
     {
-        wxPizza* pizza = WX_PIZZA(m_parent->m_wxwindow);
+        wxPizza* pizza = WX_PIZZA(parent);
         dx = pizza->m_scroll_x;
         dy = pizza->m_scroll_y;
     }
-
-    if (m_x == -1 && m_y == -1)
-    {
-        GdkWindow *source = NULL;
-        if (m_wxwindow)
-            source = gtk_widget_get_window(m_wxwindow);
-        else
-            source = gtk_widget_get_window(m_widget);
-
-        if (source)
-        {
-            int org_x = 0;
-            int org_y = 0;
-            gdk_window_get_origin( source, &org_x, &org_y );
-
-            if (m_parent)
-                m_parent->ScreenToClient(&org_x, &org_y);
-
-            const_cast<wxWindowGTK*>(this)->m_x = org_x;
-            const_cast<wxWindowGTK*>(this)->m_y = org_y;
-        }
-    }
-
     if (x) (*x) = m_x - dx;
     if (y) (*y) = m_y - dy;
 }
@@ -3185,6 +3201,7 @@ void wxWindowGTK::GTKHandleFocusOutNoDeferring()
 
     wxFocusEvent event( wxEVT_KILL_FOCUS, GetId() );
     event.SetEventObject( this );
+    event.SetWindow( FindFocus() );
     GTKProcessEvent( event );
 }
 
@@ -3401,7 +3418,7 @@ bool wxWindowGTK::DoNavigateIn(int flags)
         gboolean rc;
         g_signal_emit_by_name(parent->m_widget, "focus", dir, &rc);
 
-        return rc == TRUE;
+        return rc != 0;
     }
 }
 
@@ -3558,17 +3575,20 @@ void wxWindowGTK::WarpPointer( int x, int y )
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
-    // We provide this function ourselves as it is
-    // missing in GDK (top of this file).
-
-    GdkWindow *window = NULL;
-    if (m_wxwindow)
-        window = gtk_widget_get_window(m_wxwindow);
-    else
-        window = gtk_widget_get_window(GetConnectWidget());
-
-    if (window)
-        gdk_window_warp_pointer( window, x, y );
+    ClientToScreen(&x, &y);
+    GdkDisplay* display = gtk_widget_get_display(m_widget);
+    GdkScreen* screen = gtk_widget_get_screen(m_widget);
+#ifdef __WXGTK30__
+    GdkDeviceManager* manager = gdk_display_get_device_manager(display);
+    gdk_device_warp(gdk_device_manager_get_client_pointer(manager), screen, x, y);
+#else
+#ifdef GDK_WINDOWING_X11
+    XWarpPointer(GDK_DISPLAY_XDISPLAY(display),
+        None,
+        GDK_WINDOW_XID(gdk_screen_get_root_window(screen)),
+        0, 0, 0, 0, x, y);
+#endif
+#endif
 }
 
 wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const
@@ -3617,43 +3637,31 @@ bool wxWindowGTK::ScrollPages(int pages)
 void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
                           const wxRect *rect)
 {
-    if ( !m_widget )
-    {
-        // it is valid to call Refresh() for a window which hasn't been created
-        // yet, it simply doesn't do anything in this case
-        return;
-    }
-
-    if (!m_wxwindow)
+    if (m_wxwindow)
     {
-        if (rect)
-            gtk_widget_queue_draw_area( m_widget, rect->x, rect->y, rect->width, rect->height );
-        else
-            gtk_widget_queue_draw( m_widget );
+        if (gtk_widget_get_mapped(m_wxwindow))
+        {
+            GdkWindow* window = gtk_widget_get_window(m_wxwindow);
+            if (rect)
+            {
+                GdkRectangle r = { rect->x, rect->y, rect->width, rect->height };
+                if (GetLayoutDirection() == wxLayout_RightToLeft)
+                    r.x = gdk_window_get_width(window) - r.x - rect->width;
+                gdk_window_invalidate_rect(window, &r, true);
+            }
+            else
+                gdk_window_invalidate_rect(window, NULL, true);
+        }
     }
-    else
+    else if (m_widget)
     {
-        // Just return if the widget or one of its ancestors isn't mapped
-        GtkWidget *w;
-        for (w = m_wxwindow; w != NULL; w = gtk_widget_get_parent(w))
-            if (!gtk_widget_get_mapped (w))
-                return;
-
-        GdkWindow* window = GTKGetDrawingWindow();
-        if (rect)
+        if (gtk_widget_get_mapped(m_widget))
         {
-            int x = rect->x;
-            if (GetLayoutDirection() == wxLayout_RightToLeft)
-                x = GetClientSize().x - x - rect->width;
-            GdkRectangle r;
-            r.x = rect->x;
-            r.y = rect->y;
-            r.width = rect->width;
-            r.height = rect->height;
-            gdk_window_invalidate_rect(window, &r, true);
+            if (rect)
+                gtk_widget_queue_draw_area(m_widget, rect->x, rect->y, rect->width, rect->height);
+            else
+                gtk_widget_queue_draw(m_widget);
         }
-        else
-            gdk_window_invalidate_rect(window, NULL, true);
     }
 }
 
@@ -3696,7 +3704,9 @@ void wxWindowGTK::GtkSendPaintEvents()
         m_updateRegion.Clear();
         return;
     }
-
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+    cairo_t* cr = NULL;
+#endif
     // Clip to paint region in wxClientDC
     m_clipPaintRegion = true;
 
@@ -3728,6 +3738,27 @@ void wxWindowGTK::GtkSendPaintEvents()
 
     switch ( GetBackgroundStyle() )
     {
+        case wxBG_STYLE_TRANSPARENT:
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+            if (IsTransparentBackgroundSupported())
+            {
+                // Set a transparent background, so that overlaying in parent
+                // might indeed let see through where this child did not
+                // explicitly paint.
+                // NB: it works also for top level windows (but this is the
+                // windows manager which then does the compositing job)
+                cr = gdk_cairo_create(m_wxwindow->window);
+                gdk_cairo_region(cr, m_nativeUpdateRegion.GetRegion());
+                cairo_clip(cr);
+
+                cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+                cairo_paint(cr);
+                cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+                cairo_surface_flush(cairo_get_target(cr));
+            }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+            break;
+
         case wxBG_STYLE_ERASE:
             {
                 wxWindowDC dc( (wxWindow*)this );
@@ -3804,6 +3835,39 @@ void wxWindowGTK::GtkSendPaintEvents()
     paint_event.SetEventObject( this );
     HandleWindowEvent( paint_event );
 
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+    if (IsTransparentBackgroundSupported())
+    { // now composite children which need it
+        // Overlay all our composite children on top of the painted area
+        wxWindowList::compatibility_iterator node;
+        for ( node = m_children.GetFirst(); node ; node = node->GetNext() )
+        {
+            wxWindow *compositeChild = node->GetData();
+            if (compositeChild->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT)
+            {
+                if (cr == NULL)
+                {
+                    cr = gdk_cairo_create(m_wxwindow->window);
+                    gdk_cairo_region(cr, m_nativeUpdateRegion.GetRegion());
+                    cairo_clip(cr);
+                }
+
+                GtkWidget *child = compositeChild->m_wxwindow;
+                GtkAllocation alloc;
+                gtk_widget_get_allocation(child, &alloc);
+
+                // The source data is the (composited) child
+                gdk_cairo_set_source_window(
+                    cr, gtk_widget_get_window(child), alloc.x, alloc.y);
+
+                cairo_paint(cr);
+            }
+        }
+        if (cr)
+            cairo_destroy(cr);
+    }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+
     m_clipPaintRegion = false;
 
     m_updateRegion.Clear();
@@ -3820,7 +3884,7 @@ void wxWindowGTK::SetDoubleBuffered( bool on )
 
 bool wxWindowGTK::IsDoubleBuffered() const
 {
-    return gtk_widget_get_double_buffered( m_wxwindow );
+    return gtk_widget_get_double_buffered( m_wxwindow ) != 0;
 }
 
 void wxWindowGTK::ClearBackground()
@@ -4007,35 +4071,34 @@ void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style)
 
 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 {
-    wxWindowBase::SetBackgroundStyle(style);
+    if (!wxWindowBase::SetBackgroundStyle(style))
+        return false;
 
-    if ( style == wxBG_STYLE_PAINT )
+    GdkWindow *window;
+    if ( m_wxwindow )
     {
-        GdkWindow *window;
-        if ( m_wxwindow )
-        {
-            window = GTKGetDrawingWindow();
-        }
-        else
-        {
-            GtkWidget * const w = GetConnectWidget();
-            window = w ? gtk_widget_get_window(w) : NULL;
-        }
+        window = GTKGetDrawingWindow();
+    }
+    else
+    {
+        GtkWidget * const w = GetConnectWidget();
+        window = w ? gtk_widget_get_window(w) : NULL;
+    }
 
+    bool wantNoBackPixmap = style == wxBG_STYLE_PAINT || style == wxBG_STYLE_TRANSPARENT;
+
+    if ( wantNoBackPixmap )
+    {
         if (window)
         {
             // Make sure GDK/X11 doesn't refresh the window
             // automatically.
-            gdk_window_set_back_pixmap( window, None, False );
-#ifdef __X__
-            Display* display = GDK_WINDOW_DISPLAY(window);
-            XFlush(display);
-#endif
+            gdk_window_set_back_pixmap( window, NULL, FALSE );
             m_needsStyleChange = false;
         }
         else // window not realized yet
         {
-            // Do in OnIdle, because the window is not yet available
+            // Do when window is realized
             m_needsStyleChange = true;
         }
 
@@ -4051,6 +4114,49 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
     return true;
 }
 
+bool wxWindowGTK::IsTransparentBackgroundSupported(wxString* reason) const
+{
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+    if (gtk_check_version(wxGTK_VERSION_REQUIRED_FOR_COMPOSITING) != NULL)
+    {
+        if (reason)
+        {
+            *reason = _("GTK+ installed on this machine is too old to "
+                        "support screen compositing, please install "
+                        "GTK+ 2.12 or later.");
+        }
+
+        return false;
+    }
+
+    // NB: We don't check here if the particular kind of widget supports
+    // transparency, we check only if it would be possible for a generic window
+
+    wxCHECK_MSG ( m_widget, false, "Window must be created first" );
+
+    if (!gdk_screen_is_composited(gtk_widget_get_screen(m_widget)))
+    {
+        if (reason)
+        {
+            *reason = _("Compositing not supported by this system, "
+                        "please enable it in your Window Manager.");
+        }
+
+        return false;
+    }
+
+    return true;
+#else
+    if (reason)
+    {
+        *reason = _("This program was compiled with a too old version of GTK+, "
+                    "please rebuild with GTK+ 2.12 or newer.");
+    }
+
+    return false;
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT/!wxGTK_HAS_COMPOSITING_SUPPORT
+}
+
 // ----------------------------------------------------------------------------
 // Pop-up menu stuff
 // ----------------------------------------------------------------------------
@@ -4435,12 +4541,6 @@ void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
     }
 }
 
-void wxWindowGTK::SetWindowStyleFlag( long style )
-{
-    // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already
-    wxWindowBase::SetWindowStyleFlag(style);
-}
-
 // Find the wxWindow at the current mouse position, also returning the mouse
 // position.
 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
@@ -4453,31 +4553,18 @@ wxWindow* wxFindWindowAtPointer(wxPoint& pt)
 // Get the current mouse position.
 wxPoint wxGetMousePosition()
 {
-  /* This crashes when used within wxHelpContext,
-     so we have to use the X-specific implementation below.
-    gint x, y;
-    GdkModifierType *mask;
-    (void) gdk_window_get_pointer(NULL, &x, &y, mask);
-
-    return wxPoint(x, y);
-  */
+    wxWindow* tlw = NULL;
+    if (!wxTopLevelWindows.empty())
+        tlw = wxTopLevelWindows.front();
+    GdkDisplay* display;
+    if (tlw && tlw->m_widget)
+        display = gtk_widget_get_display(tlw->m_widget);
+    else
+        display = gdk_display_get_default();
 
     int x, y;
-    GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
-
-    Display *display = windowAtPtr ? GDK_WINDOW_XDISPLAY(windowAtPtr) : GDK_DISPLAY();
-    Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
-    Window rootReturn, childReturn;
-    int rootX, rootY, winX, winY;
-    unsigned int maskReturn;
-
-    XQueryPointer (display,
-           rootWindow,
-           &rootReturn,
-                   &childReturn,
-                   &rootX, &rootY, &winX, &winY, &maskReturn);
-    return wxPoint(rootX, rootY);
-
+    gdk_display_get_pointer(display, NULL, &x, &y, NULL);
+    return wxPoint(x, y);
 }
 
 GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const