Hello community,

here is the log from the commit of package libqt5-qtbase for openSUSE:Factory 
checked in at 2016-05-17 17:06:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libqt5-qtbase (Old)
 and      /work/SRC/openSUSE:Factory/.libqt5-qtbase.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libqt5-qtbase"

Changes:
--------
--- /work/SRC/openSUSE:Factory/libqt5-qtbase/libqt5-qtbase.changes      
2016-03-18 21:28:36.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.libqt5-qtbase.new/libqt5-qtbase.changes 
2016-05-17 17:06:31.000000000 +0200
@@ -1,0 +2,50 @@
+Sat Apr 23 18:04:33 UTC 2016 - hrvoje.sen...@gmail.com
+
+- Add patches from upstream:
+  0001-xcb-XInput2-fixes-enter-leave-event-fixes.patch
+  0002-xcb-Correct-enter-leave-event-handling-when-mouse-bu.patch
+  0003-xcb-Fix-not-delivering-focusIn-event-on-hide-show.patch
+  0004-xcb-Fix-drag-and-drop-between-xcb-screens.patch
+  0005-xcb-Properly-initialize-available-geometry-when-XRan.patch
+  0006-xcb-properly-initialize-size-in-millimeters-if-XRand.patch
+  0007-xcb-Deliver-mouse-enter-event-to-window-when-closing.patch
+  0008-xcb-resourceType-names-must-have-only-small-letters.patch
+  0009-Expose-the-number-of-X-screen-through-the-QXcbScreen.patch
+  0010-xcb-mark-mouse-events-from-tablet-devices-as-synthes.patch
+  0011-xcb-Initialize-all-xcb_client_message_event_t-member.patch
+  0012-xcb-Merge-_NET_WM_STATE-hints-instead-of-overwriting.patch
+  0013-xcb-Fix-interpretation-of-the-size-from-RRCrtcChange.patch
+  0014-xcb-Properly-process-enter-leave-events.patch
+  0015-Use-the-state-of-the-key-event-to-process-it.patch
+  0016-xcb-Fix-drag-and-drop-to-applications-like-Emacs-and.patch
+
+-------------------------------------------------------------------
+Fri Mar 18 19:03:01 UTC 2016 - hrvoje.sen...@gmail.com
+
+- Update to 5.6.0
+  * For more details please see:
+    http://blog.qt.io/blog/2016/03/16/qt-5-6-released/
+    and https://wiki.qt.io/New_Features_in_Qt_5.6
+- Added patches for various QtDBus issues:
+  Fix-QtDBus-deadlock-inside-kded-kiod.patch,
+  QtDBus-clean-up-signal-hooks-and-object-tree-in-closeConnection.patch
+  and QtDBus-finish-all-pending-call-with-error-if-disconnected.patch
+- Added tell-the-truth-about-private-api.patch: mark private and QPA API
+  with symbols for only current patch release
+- Drop obsolete and/or upstreamed patches:
+  xcb-fix-yet-another-crash-when-screens-are-disconnected.patch,
+  xcb-dont-crash-in-mapToNativemapFromNative-if-the-screen-is-null.patch,
+  qtwidgets_do_not-hide_show_via_WA_OutsideWSRange_for_native_widgets.patch,
+  protect-geometry-QTBUG-40584.patch,
+  move-the-official-Qt-version-from-qglobal-to-qmake-conf.patch,
+  QMimeDatabase-follow-symlinks-when-checking-for-FIFO.patch,
+  Fix-QtCore-compilation-with-clang.patch,
+  Add-option-to-disable-session-management-by-closing-windows.patch,
+  Add-an-automatic-use-of-the-ELF-versioned-QtCore-symbol.patch,
+  Add-a-qt_version_tag-symbol-to-QtCore-that-uses-ELF-versions.patch,
+  Add-a-linker-version-script-to-Qt-libraries.patch,
+  0005-Restore-documented-behavior-for-the-WA_X11NetWmWindo.patch,
+  0001-Fix-exclusion-of-anonymous-ciphers.patch and
+  0001-Fix-QWidget-setWindowRole.patch
+
+-------------------------------------------------------------------

Old:
----
  0001-Fix-QWidget-setWindowRole.patch
  0001-Fix-exclusion-of-anonymous-ciphers.patch
  0005-Restore-documented-behavior-for-the-WA_X11NetWmWindo.patch
  Add-a-linker-version-script-to-Qt-libraries.patch
  Add-a-qt_version_tag-symbol-to-QtCore-that-uses-ELF-versions.patch
  Add-an-automatic-use-of-the-ELF-versioned-QtCore-symbol.patch
  Add-option-to-disable-session-management-by-closing-windows.patch
  Fix-QtCore-compilation-with-clang.patch
  QMimeDatabase-follow-symlinks-when-checking-for-FIFO.patch
  move-the-official-Qt-version-from-qglobal-to-qmake-conf.patch
  protect-geometry-QTBUG-40584.patch
  qtbase-opensource-src-5.5.1.tar.xz
  qtwidgets_do_not-hide_show_via_WA_OutsideWSRange_for_native_widgets.patch
  xcb-dont-crash-in-mapToNativemapFromNative-if-the-screen-is-null.patch
  xcb-fix-yet-another-crash-when-screens-are-disconnected.patch

New:
----
  0001-xcb-XInput2-fixes-enter-leave-event-fixes.patch
  0002-xcb-Correct-enter-leave-event-handling-when-mouse-bu.patch
  0003-xcb-Fix-not-delivering-focusIn-event-on-hide-show.patch
  0004-xcb-Fix-drag-and-drop-between-xcb-screens.patch
  0005-xcb-Properly-initialize-available-geometry-when-XRan.patch
  0006-xcb-properly-initialize-size-in-millimeters-if-XRand.patch
  0007-xcb-Deliver-mouse-enter-event-to-window-when-closing.patch
  0008-xcb-resourceType-names-must-have-only-small-letters.patch
  0009-Expose-the-number-of-X-screen-through-the-QXcbScreen.patch
  0010-xcb-mark-mouse-events-from-tablet-devices-as-synthes.patch
  0011-xcb-Initialize-all-xcb_client_message_event_t-member.patch
  0012-xcb-Merge-_NET_WM_STATE-hints-instead-of-overwriting.patch
  0013-xcb-Fix-interpretation-of-the-size-from-RRCrtcChange.patch
  0014-xcb-Properly-process-enter-leave-events.patch
  0015-Use-the-state-of-the-key-event-to-process-it.patch
  0016-xcb-Fix-drag-and-drop-to-applications-like-Emacs-and.patch
  Fix-QtDBus-deadlock-inside-kded-kiod.patch
  QtDBus-clean-up-signal-hooks-and-object-tree-in-closeConnection.patch
  QtDBus-finish-all-pending-call-with-error-if-disconnected.patch
  qtbase-opensource-src-5.6.0.tar.xz
  tell-the-truth-about-private-api.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libqt5-qtbase.spec ++++++
--- /var/tmp/diff_new_pack.g5HtA9/_old  2016-05-17 17:06:34.000000000 +0200
+++ /var/tmp/diff_new_pack.g5HtA9/_new  2016-05-17 17:06:34.000000000 +0200
@@ -26,15 +26,15 @@
 %endif
 
 Name:           libqt5-qtbase
-Version:        5.5.1
+Version:        5.6.0
 Release:        0
 Summary:        C++ Program Library, Core Components
 License:        GPL-3.0 or SUSE-LGPL-2.1-with-digia-exception-1.1
 Group:          System/Libraries
 Url:            http://qt.digia.com
 %define base_name libqt5
-%define real_version 5.5.1
-%define so_version 5.5.1
+%define real_version 5.6.0
+%define so_version 5.6.0
 %define tar_version qtbase-opensource-src-%{real_version}
 Source:         %{tar_version}.tar.xz
 # to get mtime of file:
@@ -47,28 +47,32 @@
 Patch2:         use-freetype-default.patch
 # PATCH-FIX-SUSE libqt5-Fix-Gujarati-font.patch bnc#878292 fix broken Gujarati 
font rendering
 Patch3:         libqt5-Fix-Gujarati-font.patch
-# PATCH-FIX-UPSTREAM protect-geometry-QTBUG-40584.patch -- 
https://bugreports.qt-project.org/browse/QTBUG-40584
-Patch4:         protect-geometry-QTBUG-40584.patch
 # Patch-FIX-SUSE libqt5-do-not-use-shm-if-display-name-doesnt-look-local.patch 
-- bnc#888858
 Patch5:         libqt5-do-not-use-shm-if-display-name-doesnt-look-local.patch
-# PATCH-FIX-UPSTREAM 0001-Fix-exclusion-of-anonymous-ciphers.patch -- Exclude 
more ciphers from being used by default
-Patch6:         0001-Fix-exclusion-of-anonymous-ciphers.patch
 # PATCH-FIX-OPENSUSE disable-rc4-ciphers-bnc865241.diff bnc#865241-- Exclude 
rc4 ciphers from being used by default
-Patch7:         disable-rc4-ciphers-bnc865241.diff
-# patches 1000-2000 and above from upstream 5.3 branch #
-# patches 2000-3000 and above from upstream 5.5 branch #
-Patch2010:      0001-Fix-QWidget-setWindowRole.patch
-Patch2014:      0005-Restore-documented-behavior-for-the-WA_X11NetWmWindo.patch
-Patch3000:      Add-a-linker-version-script-to-Qt-libraries.patch
-Patch3001:      
Add-a-qt_version_tag-symbol-to-QtCore-that-uses-ELF-versions.patch
-Patch3002:      Fix-QtCore-compilation-with-clang.patch
-Patch3003:      move-the-official-Qt-version-from-qglobal-to-qmake-conf.patch
-Patch3004:      Add-an-automatic-use-of-the-ELF-versioned-QtCore-symbol.patch
-Patch3005:      xcb-fix-yet-another-crash-when-screens-are-disconnected.patch
-Patch3006:      
xcb-dont-crash-in-mapToNativemapFromNative-if-the-screen-is-null.patch
-Patch3007:      
qtwidgets_do_not-hide_show_via_WA_OutsideWSRange_for_native_widgets.patch
-Patch3008:      
Add-option-to-disable-session-management-by-closing-windows.patch
-Patch3009:      QMimeDatabase-follow-symlinks-when-checking-for-FIFO.patch
+Patch6:         disable-rc4-ciphers-bnc865241.diff
+Patch7:         tell-the-truth-about-private-api.patch
+# patches 1000-2000 and above from upstream 5.6 branch #
+Patch1000:      0001-xcb-XInput2-fixes-enter-leave-event-fixes.patch
+Patch1001:      0002-xcb-Correct-enter-leave-event-handling-when-mouse-bu.patch
+Patch1002:      0003-xcb-Fix-not-delivering-focusIn-event-on-hide-show.patch
+Patch1003:      0004-xcb-Fix-drag-and-drop-between-xcb-screens.patch
+Patch1004:      0005-xcb-Properly-initialize-available-geometry-when-XRan.patch
+Patch1005:      0006-xcb-properly-initialize-size-in-millimeters-if-XRand.patch
+Patch1006:      0007-xcb-Deliver-mouse-enter-event-to-window-when-closing.patch
+Patch1007:      0008-xcb-resourceType-names-must-have-only-small-letters.patch
+Patch1008:      0009-Expose-the-number-of-X-screen-through-the-QXcbScreen.patch
+Patch1009:      0010-xcb-mark-mouse-events-from-tablet-devices-as-synthes.patch
+Patch1010:      0011-xcb-Initialize-all-xcb_client_message_event_t-member.patch
+Patch1011:      0012-xcb-Merge-_NET_WM_STATE-hints-instead-of-overwriting.patch
+Patch1012:      0013-xcb-Fix-interpretation-of-the-size-from-RRCrtcChange.patch
+Patch1013:      0014-xcb-Properly-process-enter-leave-events.patch
+# patches 2000-3000 and above from upstream 5.7 branch #
+Patch3000:      Fix-QtDBus-deadlock-inside-kded-kiod.patch
+Patch3001:      
QtDBus-clean-up-signal-hooks-and-object-tree-in-closeConnection.patch
+Patch3002:      QtDBus-finish-all-pending-call-with-error-if-disconnected.patch
+Patch3003:      0015-Use-the-state-of-the-key-event-to-process-it.patch
+Patch3004:      0016-xcb-Fix-drag-and-drop-to-applications-like-Emacs-and.patch
 BuildRequires:  alsa-devel
 BuildRequires:  cups-devel
 BuildRequires:  gcc-c++
@@ -109,7 +113,7 @@
 BuildRequires:  xz
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(gtk+-2.0)
-%if 0%{?is_opensuse} || 0%{?suse_version} != 1315 
+%if 0%{?is_opensuse} 
 BuildRequires:  pkgconfig(harfbuzz)
 %endif
 BuildRequires:  pkgconfig(ice)
@@ -149,25 +153,32 @@
 %setup -q -n qtbase-opensource-src-%{real_version}
 %patch2 -p1
 %patch3 -p1
-%patch4 -p1
 %patch5 -p1
 %patch6 -p1
 %patch7 -p1
-%patch2010 -p1
-%patch2014 -p1
+%patch1000 -p1
+%patch1001 -p1
+%patch1002 -p1
+%patch1003 -p1
+%patch1004 -p1
+%patch1005 -p1
+%patch1006 -p1
+%patch1007 -p1
+%patch1008 -p1
+%patch1009 -p1
+%patch1010 -p1
+%patch1011 -p1
+%patch1012 -p1
+%patch1013 -p1
 %patch3000 -p1
 %patch3001 -p1
 %patch3002 -p1
 %patch3003 -p1
 %patch3004 -p1
-%patch3005 -p1
-%patch3006 -p1
-%patch3007 -p1
-%patch3008 -p1
-%patch3009 -p1
 
 # be sure not to use them
 rm -r src/3rdparty/{libjpeg,freetype,libpng,zlib}
+#rm -r mkspecs/features/qt_module.prf.orig
 #rm -r qtimageformats/src/3rdparty/{libtiff,libmng}
 
 %package devel
@@ -175,7 +186,6 @@
 Group:          Development/Libraries/X11
 # External deps shall be found via pkgconfig
 Requires:       %{name}-common-devel
-Requires:       %{name}-doc = %{version}
 Requires:       libQt5Concurrent-devel = %{version}
 Requires:       libQt5Core-devel = %{version}
 Requires:       libQt5DBus-devel = %{version}
@@ -569,15 +579,6 @@
 %description -n libQt5Sql-private-headers-devel
 Qt 5 SQL Library - Non-ABI stable development files.
 
-%package doc
-Summary:        Qt 5 tool used by Qt Developers to generate documentation
-Group:          Development/Libraries/C and C++
-Requires:       %{name}-common-devel = %{version}
-
-%description doc
-Qt 5 tool used by Qt Developers to generate documentation for software 
projects.
-
-
 %package private-headers-devel
 Summary:        Non-ABI stable experimental API
 Group:          Development/Libraries/C and C++
@@ -749,7 +750,7 @@
        -system-libjpeg \
        -openssl-linked \
        -system-libpng \
-%if 0%{?is_opensuse} || 0%{?suse_version} != 1315 
+%if 0%{?is_opensuse}
        -system-harfbuzz \
 %endif
        -fontconfig \
@@ -895,7 +896,9 @@
 %{_bindir}/uic*
 %{libqt5_bindir}/uic*
 %{_bindir}/syncqt.pl*
+%{_bindir}/fixqt4headers.pl*
 %{libqt5_bindir}/syncqt.pl*
+%{libqt5_bindir}/fixqt4headers.pl*
 %{_bindir}/qlalr*
 %{libqt5_bindir}/qlalr*
 %{libqt5_archdatadir}/mkspecs/
@@ -923,6 +926,7 @@
 %{libqt5_libdir}/pkgconfig/Qt5Core.pc
 %{libqt5_includedir}/QtCore/
 %exclude %{libqt5_includedir}/QtCore/%{so_version}
+%{libqt5_docdir}
 
 %files -n libQt5Concurrent5
 %defattr(-,root,root,755)
@@ -1065,7 +1069,7 @@
 %{libqt5_plugindir}/platforms
 %{libqt5_plugindir}/egldeviceintegrations
 %{libqt5_plugindir}/xcbglintegrations
-%{libqt5_plugindir}/platformthemes
+%{libqt5_plugindir}/platformthemes/
 
 %files -n libQt5Gui-devel
 %defattr(-,root,root,755)
@@ -1121,19 +1125,12 @@
 %doc *.txt LICENSE.*
 %{libqt5_plugindir}/sqldrivers/libqsqlmysql*.so
 
-%files doc
-%defattr(-,root,root,755)
-%doc *.txt LICENSE.*
-%{_bindir}/qdoc*
-%{libqt5_bindir}/qdoc*
-%{libqt5_docdir}
-
 %files -n libQt5Bootstrap-devel-static
 %defattr(-,root,root,755)
 %doc *.txt LICENSE.*
 %{libqt5_libdir}/libQt5Bootstrap.a
 %{libqt5_libdir}/libQt5Bootstrap.prl
-%{libqt5_libdir}/pkgconfig/Qt5Bootstrap.pc
+#{libqt5_libdir}/pkgconfig/Qt5Bootstrap.pc
 
 %files -n libQt5OpenGLExtensions-devel-static
 %defattr(-,root,root,755)
@@ -1153,9 +1150,9 @@
 %{libqt5_libdir}/libQt5PlatformSupport.prl
 %{libqt5_libdir}/libQt5EglDeviceIntegration.prl
 %{libqt5_libdir}/libQt5XcbQpa.prl
-%{libqt5_libdir}/pkgconfig/Qt5PlatformSupport.pc
-%{libqt5_libdir}/pkgconfig/Qt5EglDeviceIntegration.pc
-%{libqt5_libdir}/pkgconfig/Qt5XcbQpa.pc
+#{libqt5_libdir}/pkgconfig/Qt5PlatformSupport.pc
+#{libqt5_libdir}/pkgconfig/Qt5EglDeviceIntegration.pc
+#{libqt5_libdir}/pkgconfig/Qt5XcbQpa.pc
 %{libqt5_includedir}/QtPlatformSupport/
 %exclude %{libqt5_includedir}/QtPlatformSupport/%{so_version}
 

++++++ 0001-xcb-XInput2-fixes-enter-leave-event-fixes.patch ++++++
>From e4c22c34fb105fc9c30be855048692d95b31c760 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spa...@wp.pl>
Date: Fri, 8 Jan 2016 19:37:52 +0100
Subject: [PATCH 01/16] xcb: XInput2 fixes, enter/leave event fixes

Added enter/leave event handling in XInput2 to avoid problems with
those events when the mouse is grabbed.

This commit amends: 53d289ec4c0f512a3475da4bbf1f940cd6838ace
This commit amends: ed2e15780385f7cf0a0d3aedc9cb2059d470bd58

Task-number: QTBUG-50340
Change-Id: I7a120b46daa4f8fa4c218346273ae90b6abfa156
Reviewed-by: Laszlo Agocs <laszlo.ag...@theqtcompany.com>
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit e4fb521b3f3b9e59146b7569b72aee08dbaeb268)
---
 src/plugins/platforms/xcb/qxcbconnection.cpp     |  16 +-
 src/plugins/platforms/xcb/qxcbconnection.h       |  12 +-
 src/plugins/platforms/xcb/qxcbconnection_xi2.cpp |  54 +++++--
 src/plugins/platforms/xcb/qxcbkeyboard.cpp       |   8 +-
 src/plugins/platforms/xcb/qxcbkeyboard.h         |   2 +
 src/plugins/platforms/xcb/qxcbwindow.cpp         | 177 ++++++++++++++---------
 src/plugins/platforms/xcb/qxcbwindow.h           |   9 ++
 7 files changed, 183 insertions(+), 95 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp 
b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 
9cedd296e1e9ad870900a09f2d955e3460484205..aeb730670d62b3ce2239fba48b58ccb4752e912d
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -613,8 +613,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface 
*nativeInterface, bool canGra
     initializeScreens();
 
     initializeXRender();
-    m_xi2Enabled = false;
 #if defined(XCB_USE_XINPUT2)
+    m_xi2Enabled = false;
     initializeXInput2();
 #endif
     initializeXShape();
@@ -1133,8 +1133,16 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t 
*event)
             handleClientMessageEvent((xcb_client_message_event_t *)event);
             break;
         case XCB_ENTER_NOTIFY:
+#ifdef XCB_USE_XINPUT22
+            if (isAtLeastXI22() && xi2MouseEvents())
+                break;
+#endif
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, 
handleEnterNotifyEvent);
         case XCB_LEAVE_NOTIFY:
+#ifdef XCB_USE_XINPUT22
+            if (isAtLeastXI22() && xi2MouseEvents())
+                break;
+#endif
             m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t 
*)event)->state);
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, 
handleLeaveNotifyEvent);
         case XCB_FOCUS_IN:
@@ -2216,13 +2224,15 @@ void QXcbConnection::initializeXKB()
 #endif
 }
 
+#if defined(XCB_USE_XINPUT22)
 bool QXcbConnection::xi2MouseEvents() const
 {
     static bool mouseViaXI2 = 
!qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
-    // Don't use XInput2 when Xinerama extension is enabled,
-    // because it causes problems with multi-monitor setup.
+    // FIXME: Don't use XInput2 mouse events when Xinerama extension
+    // is enabled, because it causes problems with multi-monitor setup.
     return mouseViaXI2 && !has_xinerama_extension;
 }
+#endif
 
 #if defined(XCB_USE_XINPUT2)
 static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h 
b/src/plugins/platforms/xcb/qxcbconnection.h
index 
a6a7b9e7ca1898fe2add7a51107bfc9e535d9b44..6c2b8583af24e9abd7a087144fb33504ec36fbf8
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -347,8 +347,10 @@ public:
     virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {}
     virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {}
     virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t 
*) {}
+#ifdef XCB_USE_XINPUT22
     virtual void handleXIMouseEvent(xcb_ge_event_t *) {}
-
+    virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
+#endif
     virtual QXcbWindow *toWindow() { return 0; }
 };
 
@@ -485,8 +487,8 @@ public:
     static bool xEmbedSystemTrayAvailable();
     static bool xEmbedSystemTrayVisualHasAlphaChannel();
 
-#ifdef XCB_USE_XINPUT2
-    void handleEnterEvent(const xcb_enter_notify_event_t *);
+#ifdef XCB_USE_XINPUT21
+    void handleEnterEvent();
 #endif
 
 #ifdef XCB_USE_XINPUT22
@@ -500,7 +502,9 @@ public:
 
     QXcbGlIntegration *glIntegration() const { return m_glIntegration; }
 
+#ifdef XCB_USE_XINPUT22
     bool xi2MouseEvents() const;
+#endif
 
 protected:
     bool event(QEvent *e) Q_DECL_OVERRIDE;
@@ -534,9 +538,9 @@ private:
     void initializeScreens();
     bool compressEvent(xcb_generic_event_t *event, int currentIndex, 
QXcbEventArray *eventqueue) const;
 
+#ifdef XCB_USE_XINPUT2
     bool m_xi2Enabled;
     int m_xi2Minor;
-#ifdef XCB_USE_XINPUT2
     void initializeXInput2();
     void finalizeXInput2();
     void xi2SetupDevices();
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp 
b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 
e055ad1424f9ec51a5f4e814babd85601c920c90..0c78c0e0d2bc9d05e9f6768ead72cad4a51d03a7
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -293,6 +293,11 @@ void QXcbConnection::xi2Select(xcb_window_t window)
             bitMask |= XI_ButtonPressMask;
             bitMask |= XI_ButtonReleaseMask;
             bitMask |= XI_MotionMask;
+
+            // There is a check for enter/leave events in plain xcb 
enter/leave event handler
+            bitMask |= XI_EnterMask;
+            bitMask |= XI_LeaveMask;
+
             qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion 
events in addition to touch");
         }
         XIEventMask mask;
@@ -307,9 +312,12 @@ void QXcbConnection::xi2Select(xcb_window_t window)
         if (result != Success)
             qCDebug(lcQpaXInput, "XInput 2.2: failed to select pointer/touch 
events, window %x, result %d", window, result);
     }
-#endif // XCB_USE_XINPUT22
 
     const bool pointerSelected = isAtLeastXI22() && xi2MouseEvents();
+#else
+    const bool pointerSelected = false;
+#endif // XCB_USE_XINPUT22
+
     QSet<int> tabletDevices;
 #ifndef QT_NO_TABLETEVENT
     if (!m_tabletData.isEmpty()) {
@@ -474,6 +482,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
     xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent 
*>(event);
     int sourceDeviceId = xiEvent->deviceid; // may be the master id
     xXIDeviceEvent *xiDeviceEvent = 0;
+    xXIEnterEvent *xiEnterEvent = 0;
     QXcbWindowEventListener *eventListener = 0;
 
     switch (xiEvent->evtype) {
@@ -488,14 +497,16 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
     {
         xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
         eventListener = windowEventListenerFromId(xiDeviceEvent->event);
-        if (eventListener) {
-            long result = 0;
-            if 
(eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t 
*>(event), &result))
-                return;
-        }
         sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id 
instead of the master
         break;
     }
+    case XI_Enter:
+    case XI_Leave: {
+        xiEnterEvent = reinterpret_cast<xXIEnterEvent *>(event);
+        eventListener = windowEventListenerFromId(xiEnterEvent->event);
+        sourceDeviceId = xiEnterEvent->sourceid; // use the actual device id 
instead of the master
+        break;
+    }
     case XI_HierarchyChanged:
         xi2HandleHierachyEvent(xiEvent);
         return;
@@ -506,11 +517,19 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
         break;
     }
 
+    if (eventListener) {
+        long result = 0;
+        if 
(eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t 
*>(event), &result))
+            return;
+    }
+
 #ifndef QT_NO_TABLETEVENT
-    for (int i = 0; i < m_tabletData.count(); ++i) {
-        if (m_tabletData.at(i).deviceId == sourceDeviceId) {
-            if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
-                return;
+    if (!xiEnterEvent) {
+        for (int i = 0; i < m_tabletData.count(); ++i) {
+            if (m_tabletData.at(i).deviceId == sourceDeviceId) {
+                if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], 
eventListener))
+                    return;
+            }
         }
     }
 #endif // QT_NO_TABLETEVENT
@@ -543,6 +562,13 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
                 xi2ProcessTouch(xiDeviceEvent, platformWindow);
             break;
         }
+    } else if (xiEnterEvent && xi2MouseEvents() && eventListener) {
+        switch (xiEnterEvent->evtype) {
+        case XI_Enter:
+        case XI_Leave:
+            eventListener->handleXIEnterLeave(event);
+            break;
+        }
     }
 #endif // XCB_USE_XINPUT22
 }
@@ -718,6 +744,8 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, 
bool grab)
     XISetMask(mask, XI_ButtonPress);
     XISetMask(mask, XI_ButtonRelease);
     XISetMask(mask, XI_Motion);
+    XISetMask(mask, XI_Enter);
+    XISetMask(mask, XI_Leave);
     XISetMask(mask, XI_TouchBegin);
     XISetMask(mask, XI_TouchUpdate);
     XISetMask(mask, XI_TouchEnd);
@@ -827,9 +855,9 @@ void QXcbConnection::updateScrollingDevice(ScrollingDevice 
&scrollingDevice, int
 #endif
 }
 
-void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
-{
 #ifdef XCB_USE_XINPUT21
+void QXcbConnection::handleEnterEvent()
+{
     QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin();
     const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end();
     while (it != end) {
@@ -845,8 +873,8 @@ void QXcbConnection::handleEnterEvent(const 
xcb_enter_notify_event_t *)
         XIFreeDeviceInfo(xiDeviceInfo);
         ++it;
     }
-#endif
 }
+#endif
 
 void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice 
&scrollingDevice)
 {
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp 
b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 
2e088d3ca51dfff7fcf41f476b4f8db7c8f40543..631dd17908f458533f413409773b6c078b743d98
 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -797,9 +797,9 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
     }
 }
 
+#ifdef XCB_USE_XINPUT22
 void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
 {
-#ifdef XCB_USE_XINPUT22
     if (m_config && !connection()->hasXKB()) {
         xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
         xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
@@ -815,12 +815,8 @@ void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, 
void *groupInfo)
             //qWarning("TODO: Support KeyboardLayoutChange on QPA 
(QTBUG-27681)");
         }
     }
-#else
-    Q_UNUSED(modInfo);
-    Q_UNUSED(groupInfo);
-    Q_ASSERT(false); // this can't be
-#endif
 }
+#endif
 
 quint32 QXcbKeyboard::xkbModMask(quint16 state)
 {
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h 
b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 
d2e37d624cfe5960bf50d8f18f2a82756824fa4d..457a27affb166e2a3e54c78761361ff3713a4d18
 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -68,7 +68,9 @@ public:
     void updateXKBMods();
     quint32 xkbModMask(quint16 state);
     void updateXKBStateFromCore(quint16 state);
+#ifdef XCB_USE_XINPUT22
     void updateXKBStateFromXI(void *modInfo, void *groupInfo);
+#endif
 #ifndef QT_NO_XKB
     // when XKEYBOARD is present on the X server
     int coreDeviceId() const { return core_device_id; }
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
f97f570831a099c7d1d87cb12ed3c44baa7237eb..91c5eadf3456e15467ba94dd72a886a365aa6a7d
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2157,6 +2157,78 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, 
int event_y, int root_x,
     handleMouseEvent(timestamp, local, global, modifiers);
 }
 
+static bool ignoreLeaveEvent(quint8 mode, quint8 detail)
+{
+    return (mode == XCB_NOTIFY_MODE_GRAB && detail == 
XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
+            || detail == XCB_NOTIFY_DETAIL_VIRTUAL
+            || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL;
+}
+
+static bool ignoreEnterEvent(quint8 mode, quint8 detail)
+{
+    return ((mode == XCB_NOTIFY_MODE_UNGRAB && detail == 
XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
+            || (mode != XCB_NOTIFY_MODE_NORMAL && mode != 
XCB_NOTIFY_MODE_UNGRAB)
+            || detail == XCB_NOTIFY_DETAIL_VIRTUAL
+            || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
+}
+
+class EnterEventChecker
+{
+public:
+    bool checkEvent(xcb_generic_event_t *event)
+    {
+        if (!event)
+            return false;
+        if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY)
+            return false;
+
+        xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
+        if (ignoreEnterEvent(enter->mode, enter->detail))
+            return false;
+
+        return true;
+    }
+};
+
+void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, 
int root_y,
+                                        quint8 mode, quint8 detail, 
xcb_timestamp_t timestamp)
+{
+    connection()->setTime(timestamp);
+#ifdef XCB_USE_XINPUT21
+    connection()->handleEnterEvent();
+#endif
+
+    if (ignoreEnterEvent(mode, detail))
+        return;
+
+    const QPoint local(event_x, event_y);
+    QPoint global = QPoint(root_x, root_y);
+    QWindowSystemInterface::handleEnterEvent(window(), local, global);
+}
+
+void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
+                                        quint8 mode, quint8 detail, 
xcb_timestamp_t timestamp)
+{
+    connection()->setTime(timestamp);
+
+    if (ignoreLeaveEvent(mode, detail))
+        return;
+
+    EnterEventChecker checker;
+    xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t 
*)connection()->checkEvent(checker);
+    QXcbWindow *enterWindow = enter ? 
connection()->platformWindowFromId(enter->event) : 0;
+
+    if (enterWindow) {
+        QPoint local(enter->event_x, enter->event_y);
+        QPoint global = QPoint(root_x, root_y);
+        QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), 
window(), local, global);
+    } else {
+        QWindowSystemInterface::handleLeaveEvent(window());
+    }
+
+    free(enter);
+}
+
 void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, 
int root_y,
                                          Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp)
 {
@@ -2191,12 +2263,10 @@ static inline int fixed1616ToInt(FP1616 val)
 {
     return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF);
 }
-#endif
 
 // With XI 2.2+ press/release/motion comes here instead of the above handlers.
 void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
 {
-#ifdef XCB_USE_XINPUT22
     QXcbConnection *conn = connection();
     xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event);
     const Qt::KeyboardModifiers modifiers = 
conn->keyboard()->translateModifiers(ev->mods.effective_mods);
@@ -2234,12 +2304,41 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t 
*event)
         qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
         break;
     }
-#else
-    Q_UNUSED(event);
-    Q_ASSERT(false); // this can't be
-#endif
 }
 
+// With XI 2.2+ enter/leave comes here and are blocked in plain xcb events
+void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
+{
+    xXIEnterEvent *ev = reinterpret_cast<xXIEnterEvent *>(event);
+
+    // Compare the window with current mouse grabber to prevent deliver events 
to any other windows.
+    // If leave event occurs and the window is under mouse - allow to deliver 
the leave event.
+    QXcbWindow *mouseGrabber = connection()->mouseGrabber();
+    if (mouseGrabber && mouseGrabber != this
+            && (ev->evtype != XI_Leave || 
QGuiApplicationPrivate::currentMouseWindow != window())) {
+        return;
+    }
+
+    const int root_x = fixed1616ToInt(ev->root_x);
+    const int root_y = fixed1616ToInt(ev->root_y);
+
+    switch (ev->evtype) {
+    case XI_Enter: {
+        const int event_x = fixed1616ToInt(ev->event_x);
+        const int event_y = fixed1616ToInt(ev->event_y);
+        qCDebug(lcQpaXInput, "XI2 mouse enter %d,%d, mode %d, detail %d, time 
%d", event_x, event_y, ev->mode, ev->detail, ev->time);
+        handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, 
ev->detail, ev->time);
+        break;
+    }
+    case XI_Leave:
+        qCDebug(lcQpaXInput, "XI2 mouse leave, mode %d, detail %d, time %d", 
ev->mode, ev->detail, ev->time);
+        connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
+        handleLeaveNotifyEvent(root_x, root_y, ev->mode, ev->detail, ev->time);
+        break;
+    }
+}
+#endif
+
 QXcbWindow *QXcbWindow::toWindow() { return this; }
 
 void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, 
const QPoint &global, Qt::KeyboardModifiers modifiers)
@@ -2248,74 +2347,14 @@ void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, 
const QPoint &local, con
     QWindowSystemInterface::handleMouseEvent(window(), time, local, global, 
connection()->buttons(), modifiers);
 }
 
-static bool ignoreLeaveEvent(const xcb_leave_notify_event_t *event)
-{
-    return event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
-            || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL
-            || event->mode == XCB_NOTIFY_MODE_GRAB;
-}
-
-static bool ignoreEnterEvent(const xcb_enter_notify_event_t *event)
-{
-    return (event->mode != XCB_NOTIFY_MODE_NORMAL
-            || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
-            || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
-}
-
-class EnterEventChecker
-{
-public:
-    bool checkEvent(xcb_generic_event_t *event)
-    {
-        if (!event)
-            return false;
-        if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY)
-            return false;
-
-        xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
-        if (ignoreEnterEvent(enter))
-            return false;
-
-        return true;
-    }
-};
-
 void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
 {
-    connection()->setTime(event->time);
-#ifdef XCB_USE_XINPUT2
-    connection()->handleEnterEvent(event);
-#endif
-
-    if (ignoreEnterEvent(event))
-        return;
-
-    const QPoint local(event->event_x, event->event_y);
-    QPoint global = QPoint(event->root_x, event->root_y);
-    QWindowSystemInterface::handleEnterEvent(window(), local, global);
+    handleEnterNotifyEvent(event->event_x, event->event_y, event->root_x, 
event->root_y, event->mode, event->detail, event->time);
 }
 
 void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
 {
-    connection()->setTime(event->time);
-
-    if (ignoreLeaveEvent(event))
-        return;
-
-    EnterEventChecker checker;
-    xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t 
*)connection()->checkEvent(checker);
-    QXcbWindow *enterWindow = enter ? 
connection()->platformWindowFromId(enter->event) : 0;
-
-    if (enterWindow) {
-        QPoint local(enter->event_x, enter->event_y);
-        QPoint global = QPoint(event->root_x, event->root_y);
-
-        QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), 
window(), local, global);
-    } else {
-        QWindowSystemInterface::handleLeaveEvent(window());
-    }
-
-    free(enter);
+    handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, 
event->detail, event->time);
 }
 
 void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t 
*event)
@@ -2419,7 +2458,7 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
     if (!grab && connection()->mouseGrabber() == this)
         connection()->setMouseGrabber(Q_NULLPTR);
 #ifdef XCB_USE_XINPUT22
-    if (connection()->xi2MouseEvents()) {
+    if (connection()->isAtLeastXI22() && connection()->xi2MouseEvents()) {
         bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab);
         if (grab && result)
             connection()->setMouseGrabber(this);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h 
b/src/plugins/platforms/xcb/qxcbwindow.h
index 
d2c02fe3df4e0d0667711dfa9bfc10fed30d9554..69790f29ae098bbfcc5aa6edec75e3d0fea8ea75
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -132,7 +132,10 @@ public:
     void handleFocusInEvent(const xcb_focus_in_event_t *event) Q_DECL_OVERRIDE;
     void handleFocusOutEvent(const xcb_focus_out_event_t *event) 
Q_DECL_OVERRIDE;
     void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) 
Q_DECL_OVERRIDE;
+#ifdef XCB_USE_XINPUT22
     void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE;
+    void handleXIEnterLeave(xcb_ge_event_t *) Q_DECL_OVERRIDE;
+#endif
 
     QXcbWindow *toWindow() Q_DECL_OVERRIDE;
 
@@ -212,6 +215,12 @@ protected:
     void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int 
root_y,
                                  Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp);
 
+    void handleEnterNotifyEvent(int event_x, int event_y, int root_x, int 
root_y,
+                                quint8 mode, quint8 detail, xcb_timestamp_t 
timestamp);
+
+    void handleLeaveNotifyEvent(int root_x, int root_y,
+                                quint8 mode, quint8 detail, xcb_timestamp_t 
timestamp);
+
     xcb_window_t m_window;
 
     uint m_depth;
-- 
2.6.6

++++++ 0002-xcb-Correct-enter-leave-event-handling-when-mouse-bu.patch ++++++
>From 592f96911bf453dcdc6ae14814927303db544ac8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spa...@wp.pl>
Date: Sat, 17 Oct 2015 17:22:16 +0200
Subject: [PATCH 02/16] xcb: Correct enter/leave event handling when mouse
 button is pressed

This patch fixes cursor shape when mouse leaves the window and enters
the window again with pressed mouse button - ignore the mouse enter
and leave event when any of mouse buttons is pressed.

Task-number: QTBUG-46576
Change-Id: Id6ce50cd0d66da51a251d4811bc42cd31606de29
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit b9f76db30d261421e4da58f29053181af04ceb4d)
---
 src/plugins/platforms/xcb/qxcbwindow.cpp | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
91c5eadf3456e15467ba94dd72a886a365aa6a7d..354c29152fadd9200e8d10bc245aed89526a5f6e
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2198,11 +2198,14 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, 
int event_y, int root_x, in
     connection()->handleEnterEvent();
 #endif
 
-    if (ignoreEnterEvent(mode, detail))
+    const QPoint global = QPoint(root_x, root_y);
+
+    if (ignoreEnterEvent(mode, detail)
+            || (connection()->buttons() != Qt::NoButton
+                && QGuiApplicationPrivate::lastCursorPosition != global))
         return;
 
     const QPoint local(event_x, event_y);
-    QPoint global = QPoint(root_x, root_y);
     QWindowSystemInterface::handleEnterEvent(window(), local, global);
 }
 
@@ -2211,7 +2214,11 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int 
root_y,
 {
     connection()->setTime(timestamp);
 
-    if (ignoreLeaveEvent(mode, detail))
+    const QPoint global(root_x, root_y);
+
+    if (ignoreLeaveEvent(mode, detail)
+            || (connection()->buttons() != Qt::NoButton
+                && QGuiApplicationPrivate::lastCursorPosition != global))
         return;
 
     EnterEventChecker checker;
-- 
2.6.6

++++++ 0003-xcb-Fix-not-delivering-focusIn-event-on-hide-show.patch ++++++
>From f371c645e2a06234355693551e16d69961839ac1 Mon Sep 17 00:00:00 2001
From: Alexander Bersenev <b...@hackerdom.ru>
Date: Fri, 6 Nov 2015 01:39:27 +0500
Subject: [PATCH 03/16] xcb: Fix not delivering focusIn event on hide/show
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Consider a window which was hidden and shown with hide() and show()
methods and mouse pointer was in window when hide() was called.

At first, window got focusOutEvent and then Qt library sends X server
a message to unmap the window.

Then X server will send client two messages:
1) FocusOut(10) detail=Nonlinear(0x03)
2) FocusIn(9) detail=Pointer(0x05)

QXcbWindow has a logic for not seting active window to 0 if there is
a FocusIn coming (see QXcbWindow::doFocusOut).

So QGuiApplicationPrivate::focus_window still points to the current
window.

Then when show() is called, qt compares previous focus with new focus
and, since they are equal, doesn't do anything. Event focusInEvent
isn't delivered to the window.

Here are two links why X server sends FocusIn just after FocusOut:
http://lists.freedesktop.org/archives/xorg/2008-December/041684.html
https://tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html

Proposed fix ignores FocusIn events with detail==Pointer.
The text of explaining comment is taken from the Chromium project:
https://chromium.googlesource.com/chromium/src/+/master/ui/views/widget/desktop_aura/x11_desktop_handler.cc
from X11DesktopHandler::ProcessXEvent function.

[ChangeLog][module][Linux/XCB] Fix not delivering focusIn event on
hide/show with XCB

Task-number: QTBUG-49071
Change-Id: I433c8b638834c25f113cc134ee4185778c44f540
Reviewed-by: André Hartmann <aha_1...@gmx.de>
Reviewed-by: Lisandro Damián Nicanor Pérez Meyer <perezme...@gmail.com>
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit 8eaf3352590690079735eda9fb872ec8c9c58f0a)
---
 src/plugins/platforms/xcb/qxcbwindow.cpp | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
354c29152fadd9200e8d10bc245aed89526a5f6e..46b7b70f8025a8481ab2db37257a52494a84d234
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -894,8 +894,13 @@ static bool focusInPeeker(QXcbConnection *connection, 
xcb_generic_event_t *event
         return true;
     }
     uint response_type = event->response_type & ~0x80;
-    if (response_type == XCB_FOCUS_IN)
-        return true;
+    if (response_type == XCB_FOCUS_IN) {
+        // Ignore focus events that are being sent only because the pointer is 
over
+        // our window, even if the input focus is in a different window.
+        xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) event;
+        if (e->detail != XCB_NOTIFY_DETAIL_POINTER)
+            return true;
+    }
 
     /* We are also interested in XEMBED_FOCUS_IN events */
     if (response_type == XCB_CLIENT_MESSAGE) {
@@ -2415,14 +2420,22 @@ void QXcbWindow::handlePropertyNotifyEvent(const 
xcb_property_notify_event_t *ev
     }
 }
 
-void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *)
+void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *event)
 {
+    // Ignore focus events that are being sent only because the pointer is over
+    // our window, even if the input focus is in a different window.
+    if (event->detail == XCB_NOTIFY_DETAIL_POINTER)
+        return;
     doFocusIn();
 }
 
 
-void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *)
+void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *event)
 {
+    // Ignore focus events that are being sent only because the pointer is over
+    // our window, even if the input focus is in a different window.
+    if (event->detail == XCB_NOTIFY_DETAIL_POINTER)
+        return;
     doFocusOut();
 }
 
-- 
2.6.6

++++++ 0004-xcb-Fix-drag-and-drop-between-xcb-screens.patch ++++++
>From a9b7b17655d7b0826c5adc36f66407283564eb72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spa...@wp.pl>
Date: Mon, 15 Feb 2016 20:50:16 +0100
Subject: [PATCH 04/16] xcb: Fix drag and drop between xcb screens

Set the proper screen before creating a shaped pixmap window in
QBasicDrag::startDrag(). Grab mouse again when D&D window is
recreated.

Task-number: QTBUG-51215
Change-Id: I5cb47d3b11672b56d17b32072d84a722bdcdcd9a
Reviewed-by: Friedemann Kleint <friedemann.kle...@theqtcompany.com>
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit 78ad8f208d8dbe3575194bb9b97d4e42efdc32d5)
---
 src/gui/kernel/qsimpledrag.cpp         | 5 +++--
 src/gui/kernel/qsimpledrag_p.h         | 3 +++
 src/plugins/platforms/xcb/qxcbdrag.cpp | 4 ++++
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index 
9f38c9b78ad4f8537e9e4c3a39af9d2c56fb67c7..00589d23039ed4f043d026e89187d645ad2ee214
 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -88,7 +88,8 @@ static QWindow* topLevelAt(const QPoint &pos)
 QBasicDrag::QBasicDrag() :
     m_restoreCursor(false), m_eventLoop(0),
     m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false),
-    m_drag(0), m_drag_icon_window(0), m_useCompositing(true)
+    m_drag(0), m_drag_icon_window(0), m_useCompositing(true),
+    m_screen(Q_NULLPTR)
 {
 }
 
@@ -211,7 +212,7 @@ void QBasicDrag::startDrag()
         pos = QPoint();
     }
 #endif
-    recreateShapedPixmapWindow(Q_NULLPTR, pos);
+    recreateShapedPixmapWindow(m_screen, pos);
     enableEventFilter();
 }
 
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h
index 
055136c436ed3b3504c2ee564e49cee1bd4439d4..b208c8ccc97a668205ef08fdce591e4c0d78c939
 100644
--- a/src/gui/kernel/qsimpledrag_p.h
+++ b/src/gui/kernel/qsimpledrag_p.h
@@ -90,6 +90,8 @@ protected:
     bool useCompositing() const { return m_useCompositing; }
     void setUseCompositing(bool on) { m_useCompositing = on; }
 
+    void setScreen(QScreen *screen) { m_screen = screen; }
+
     Qt::DropAction executedDropAction() const { return m_executed_drop_action; 
}
     void  setExecutedDropAction(Qt::DropAction da) { m_executed_drop_action = 
da; }
 
@@ -108,6 +110,7 @@ private:
     QDrag *m_drag;
     QShapedPixmapWindow *m_drag_icon_window;
     bool m_useCompositing;
+    QScreen *m_screen;
 };
 
 class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp 
b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 
9296a6d1410f72d00efcf8c249bdd8a037b8b4be..aa6445d2da56f09696c98cba76baf6c74e44841c
 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -193,6 +193,7 @@ void QXcbDrag::startDrag()
                             XCB_ATOM_ATOM, 32, drag_types.size(), (const void 
*)drag_types.constData());
 
     setUseCompositing(current_virtual_desktop->compositingActive());
+    setScreen(current_virtual_desktop->screens().constFirst()->screen());
     QBasicDrag::startDrag();
     if (connection()->mouseGrabber() == Q_NULLPTR)
         shapedPixmapWindow()->setMouseGrabEnabled(true);
@@ -322,6 +323,9 @@ void QXcbDrag::move(const QPoint &globalPos)
     if (virtualDesktop != current_virtual_desktop) {
         setUseCompositing(virtualDesktop->compositingActive());
         
recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), 
deviceIndependentPos);
+        if (connection()->mouseGrabber() == Q_NULLPTR)
+            shapedPixmapWindow()->setMouseGrabEnabled(true);
+
         current_virtual_desktop = virtualDesktop;
     } else {
         QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos);
-- 
2.6.6

++++++ 0005-xcb-Properly-initialize-available-geometry-when-XRan.patch ++++++
>From bbfc5818bb9f8d87d64f6b6f94bbfe1cea199ec9 Mon Sep 17 00:00:00 2001
From: Alexander Volkov <a.vol...@rusbitech.ru>
Date: Thu, 18 Feb 2016 18:12:57 +0300
Subject: [PATCH 05/16] xcb: Properly initialize available geometry when XRandR
 is missing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Take an intersection of the screen geometry and the work area.

Change-Id: Ia61d090ac103cb4d13d656ec09037f642b255a79
Reviewed-by: Błażej Szczygieł <spa...@wp.pl>
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit 7cd23a7d5f5b7b10c0e317afcf8bc49020a42e53)
---
 src/plugins/platforms/xcb/qxcbscreen.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp 
b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 
f3d381b99e014116317286b791a0876ad6d8ca6d..0ef7166b9076e47fc71d4b2106cbfdc6420166d3
 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -208,7 +208,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, 
QXcbVirtualDesktop *virtualDe
         m_geometry = QRect(QPoint(), m_virtualSize);
 
     if (m_availableGeometry.isEmpty())
-        m_availableGeometry = m_geometry;
+        m_availableGeometry = m_geometry & m_virtualDesktop->workArea();
 
     readXResources();
 
-- 
2.6.6

++++++ 0006-xcb-properly-initialize-size-in-millimeters-if-XRand.patch ++++++
>From 412a0b8502614ff6fac6b6b45c48091a19d67014 Mon Sep 17 00:00:00 2001
From: Shawn Rutledge <shawn.rutle...@digia.com>
Date: Thu, 18 Feb 2016 14:05:39 +0100
Subject: [PATCH 06/16] xcb: properly initialize size in millimeters if XRandR
 is not supported
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

QXcbScreen did not set the m_sizeMillimeters if the xcb connection does
not support XRandR. This caused physicalSize() to return an invalid QSize.

This change fixes a regression compared to Qt 5.4 discovered by a
broken unit test for KWin on KDE's CI system, which uses Xvfb and by
that no XRandR support.

Task-number: QTBUG-49885
Change-Id: Ie472a194ba410f0748ccfda8aa467727fafa10a3
Reviewed-by: Błażej Szczygieł <spa...@wp.pl>
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit 3f4eba746d23550be19dc4edafe193fa5ce0d3d4)
---
 src/plugins/platforms/xcb/qxcbscreen.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp 
b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 
0ef7166b9076e47fc71d4b2106cbfdc6420166d3..28b175371264cd445c1bd67a8d33f6de5a8fa219
 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -210,6 +210,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, 
QXcbVirtualDesktop *virtualDe
     if (m_availableGeometry.isEmpty())
         m_availableGeometry = m_geometry & m_virtualDesktop->workArea();
 
+    if (m_sizeMillimeters.isEmpty())
+        m_sizeMillimeters = m_virtualSizeMillimeters;
+
     readXResources();
 
     QScopedPointer<xcb_get_window_attributes_reply_t, 
QScopedPointerPodDeleter> rootAttribs(
-- 
2.6.6

++++++ 0007-xcb-Deliver-mouse-enter-event-to-window-when-closing.patch ++++++
>From 3ecd1178940a6fd9f486f62f711df4dc75197390 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spa...@wp.pl>
Date: Tue, 19 Jan 2016 22:32:52 +0100
Subject: [PATCH 07/16] xcb: Deliver mouse enter event to window when closing
 modal window

When a modal window is closed and the mouse is not under the modal
window - find a proper window and send a fake enter event.

Added auto test for checking enter event on window when modal window
is closed.

Task-number: QTBUG-35109
Change-Id: I370b52d386503820ac9de21e6d05fd019ca456ec
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit 7091be1b7999d93fe2126042161dcd1d8fd20026)
---
 src/plugins/platforms/xcb/qxcbwindow.cpp      |  48 +++++++
 tests/auto/gui/kernel/qwindow/BLACKLIST       |   2 +
 tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 193 ++++++++++++++++++++++++++
 3 files changed, 243 insertions(+)

diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
46b7b70f8025a8481ab2db37257a52494a84d234..7eae2d92ab39843d09cb6294f9afd7fc51260ecb
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -50,6 +50,7 @@
 #include "qxcbsystemtraytracker.h"
 
 #include <qpa/qplatformintegration.h>
+#include <qpa/qplatformcursor.h>
 
 #include <algorithm>
 
@@ -261,6 +262,26 @@ static inline XTextProperty* qstringToXTP(Display *dpy, 
const QString& s)
 }
 #endif // XCB_USE_XLIB
 
+// TODO move this into a utility function in QWindow or QGuiApplication
+static QWindow *childWindowAt(QWindow *win, const QPoint &p)
+{
+    foreach (QObject *obj, win->children()) {
+        if (obj->isWindowType()) {
+            QWindow *childWin = static_cast<QWindow *>(obj);
+            if (childWin->isVisible()) {
+                if (QWindow *recurse = childWindowAt(childWin, p))
+                    return recurse;
+            }
+        }
+    }
+    if (!win->isTopLevel()
+            && !(win->flags() & Qt::WindowTransparentForInput)
+            && win->geometry().contains(win->parent()->mapFromGlobal(p))) {
+        return win;
+    }
+    return Q_NULLPTR;
+}
+
 static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
 
 QXcbWindow::QXcbWindow(QWindow *window)
@@ -855,6 +876,33 @@ void QXcbWindow::hide()
         connection()->setMouseGrabber(Q_NULLPTR);
 
     m_mapped = false;
+
+    // Hiding a modal window doesn't send an enter event to its transient 
parent when the
+    // mouse is already over the parent window, so the enter event must be 
emulated.
+    if (window()->isModal()) {
+        // Get the cursor position at modal window screen
+        const QPoint nativePos = xcbScreen()->cursor()->pos();
+        const QPoint cursorPos = QHighDpi::fromNativePixels(nativePos, 
xcbScreen()->screenForPosition(nativePos)->screen());
+
+        // Find the top level window at cursor position.
+        // Don't use QGuiApplication::topLevelAt(): search only the virtual 
siblings of this window's screen
+        QWindow *enterWindow = Q_NULLPTR;
+        foreach (QPlatformScreen *screen, xcbScreen()->virtualSiblings()) {
+            if (screen->geometry().contains(cursorPos)) {
+                const QPoint devicePosition = 
QHighDpi::toNativePixels(cursorPos, screen->screen());
+                enterWindow = screen->topLevelAt(devicePosition);
+                break;
+            }
+        }
+
+        if (enterWindow && enterWindow != window()) {
+            // Find the child window at cursor position, otherwise use the top 
level window
+            if (QWindow *childWindow = childWindowAt(enterWindow, cursorPos))
+                enterWindow = childWindow;
+            const QPoint localPos = enterWindow->mapFromGlobal(cursorPos);
+            QWindowSystemInterface::handleEnterEvent(enterWindow, localPos, 
cursorPos);
+        }
+    }
 }
 
 static QWindow *tlWindow(QWindow *window)
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST 
b/tests/auto/gui/kernel/qwindow/BLACKLIST
index 
ee9709e68ba75bfc29903111087abe31040a059d..a34066dd7cec05f2e089582c87791e81d388a482
 100644
--- a/tests/auto/gui/kernel/qwindow/BLACKLIST
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -4,3 +4,5 @@ ubuntu-14.04
 ubuntu-14.04
 [modalWithChildWindow]
 ubuntu-14.04
+[modalWindowEnterEventOnHide_QTBUG35109]
+ubuntu-14.04
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp 
b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index 
a89f0da4d27c01a345a475ebf7fcaffb83d797c3..0cce5a072caf6a9ed63bab8c9318edbc8453e717
 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -92,6 +92,9 @@ private slots:
     void modalWithChildWindow();
     void modalWindowModallity();
     void modalWindowPosition();
+#ifndef QT_NO_CURSOR
+    void modalWindowEnterEventOnHide_QTBUG35109();
+#endif
     void windowsTransientChildren();
     void requestUpdate();
     void initTestCase();
@@ -706,10 +709,24 @@ public:
             }
         }
     }
+    bool event(QEvent *e) {
+        switch (e->type()) {
+        case QEvent::Enter:
+            ++enterEventCount;
+            break;
+        case QEvent::Leave:
+            ++leaveEventCount;
+            break;
+        default:
+            break;
+        }
+        return QWindow::event(e);
+    }
     void resetCounters() {
         mousePressedCount = mouseReleasedCount = mouseMovedCount = 
mouseDoubleClickedCount = 0;
         mouseSequenceSignature = QString();
         touchPressedCount = touchReleasedCount = touchMovedCount = 0;
+        enterEventCount = leaveEventCount = 0;
     }
 
     InputTestWindow() {
@@ -727,6 +744,7 @@ public:
     QPointF mousePressScreenPos, mouseMoveScreenPos, mousePressLocalPos;
     int touchPressedCount, touchReleasedCount, touchMovedCount;
     QEvent::Type touchEventType;
+    int enterEventCount, leaveEventCount;
 
     bool ignoreMouse, ignoreTouch;
 
@@ -1732,6 +1750,181 @@ void tst_QWindow::modalWindowPosition()
     QCOMPARE(window.geometry(), origGeo);
 }
 
+#ifndef QT_NO_CURSOR
+void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109()
+{
+    if (QGuiApplication::platformName() == QLatin1String("cocoa"))
+        QSKIP("This test fails on OS X on CI");
+
+    const QPoint center = 
QGuiApplication::primaryScreen()->availableGeometry().center();
+
+    const int childOffset = 16;
+    const QPoint rootPos = center - QPoint(m_testWindowSize.width(),
+                                           m_testWindowSize.height())/2;
+    const QPoint modalPos = rootPos + QPoint(childOffset * 5,
+                                             childOffset * 5);
+    const QPoint cursorPos = rootPos - QPoint(80, 80);
+
+    // Test whether tlw can receive the enter event
+    {
+        QCursor::setPos(cursorPos);
+        QCoreApplication::processEvents();
+
+        InputTestWindow root;
+        root.setTitle(__FUNCTION__);
+        root.setGeometry(QRect(rootPos, m_testWindowSize));
+        root.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&root));
+        root.requestActivate();
+        QVERIFY(QTest::qWaitForWindowActive(&root));
+
+        // Move the mouse over the root window, but not over the modal window.
+        QCursor::setPos(rootPos + QPoint(childOffset * 5 / 2,
+                                         childOffset * 5 / 2));
+
+        // Wait for the enter event. It must be delivered here, otherwise 
second
+        // compare can PASS because of this event even after "resetCounters()".
+        QTRY_COMPARE(root.enterEventCount, 1);
+        QTRY_COMPARE(root.leaveEventCount, 0);
+
+        QWindow modal;
+        modal.setTitle(QLatin1String("Modal - ") + __FUNCTION__);
+        modal.setTransientParent(&root);
+        modal.resize(m_testWindowSize/2);
+        modal.setFramePosition(modalPos);
+        modal.setModality(Qt::ApplicationModal);
+        modal.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&modal));
+        modal.requestActivate();
+        QVERIFY(QTest::qWaitForWindowActive(&modal));
+
+        QCoreApplication::processEvents();
+        QTRY_COMPARE(root.leaveEventCount, 1);
+
+        root.resetCounters();
+        modal.close();
+
+        // Check for the enter event
+        QTRY_COMPARE(root.enterEventCount, 1);
+    }
+
+    // Test whether child window can receive the enter event
+    {
+        QCursor::setPos(cursorPos);
+        QCoreApplication::processEvents();
+
+        QWindow root;
+        root.setTitle(__FUNCTION__);
+        root.setGeometry(QRect(rootPos, m_testWindowSize));
+
+        QWindow childLvl1;
+        childLvl1.setParent(&root);
+        childLvl1.setGeometry(childOffset,
+                              childOffset,
+                              m_testWindowSize.width() - childOffset,
+                              m_testWindowSize.height() - childOffset);
+
+        InputTestWindow childLvl2;
+        childLvl2.setParent(&childLvl1);
+        childLvl2.setGeometry(childOffset,
+                              childOffset,
+                              childLvl1.width() - childOffset,
+                              childLvl1.height() - childOffset);
+
+        root.show();
+        childLvl1.show();
+        childLvl2.show();
+
+        QVERIFY(QTest::qWaitForWindowExposed(&root));
+        root.requestActivate();
+        QVERIFY(QTest::qWaitForWindowActive(&root));
+        QVERIFY(childLvl1.isVisible());
+        QVERIFY(childLvl2.isVisible());
+
+        // Move the mouse over the child window, but not over the modal window.
+        // Be sure that the value is almost left-top of second child window for
+        // checking proper position mapping.
+        QCursor::setPos(rootPos + QPoint(childOffset * 5 / 2,
+                                         childOffset * 5 / 2));
+
+        // Wait for the enter event. It must be delivered here, otherwise 
second
+        // compare can PASS because of this event even after "resetCounters()".
+        QTRY_COMPARE(childLvl2.enterEventCount, 1);
+        QTRY_COMPARE(childLvl2.leaveEventCount, 0);
+
+        QWindow modal;
+        modal.setTitle(QLatin1String("Modal - ") + __FUNCTION__);
+        modal.setTransientParent(&root);
+        modal.resize(m_testWindowSize/2);
+        modal.setFramePosition(modalPos);
+        modal.setModality(Qt::ApplicationModal);
+        modal.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&modal));
+        modal.requestActivate();
+        QVERIFY(QTest::qWaitForWindowActive(&modal));
+
+        QCoreApplication::processEvents();
+        QTRY_COMPARE(childLvl2.leaveEventCount, 1);
+
+        childLvl2.resetCounters();
+        modal.close();
+
+        // Check for the enter event
+        QTRY_COMPARE(childLvl2.enterEventCount, 1);
+    }
+
+    // Test whether tlw can receive the enter event if mouse is over the 
invisible child windnow
+    {
+        QCursor::setPos(cursorPos);
+        QCoreApplication::processEvents();
+
+        InputTestWindow root;
+        root.setTitle(__FUNCTION__);
+        root.setGeometry(QRect(rootPos, m_testWindowSize));
+
+        QWindow child;
+        child.setParent(&root);
+        child.setGeometry(QRect(QPoint(), m_testWindowSize));
+
+        root.show();
+
+        QVERIFY(QTest::qWaitForWindowExposed(&root));
+        root.requestActivate();
+        QVERIFY(QTest::qWaitForWindowActive(&root));
+        QVERIFY(!child.isVisible());
+
+        // Move the mouse over the child window, but not over the modal window.
+        QCursor::setPos(rootPos + QPoint(childOffset * 5 / 2,
+                                         childOffset * 5 / 2));
+
+        // Wait for the enter event. It must be delivered here, otherwise 
second
+        // compare can PASS because of this event even after "resetCounters()".
+        QTRY_COMPARE(root.enterEventCount, 1);
+        QTRY_COMPARE(root.leaveEventCount, 0);
+
+        QWindow modal;
+        modal.setTitle(QLatin1String("Modal - ") + __FUNCTION__);
+        modal.setTransientParent(&root);
+        modal.resize(m_testWindowSize/2);
+        modal.setFramePosition(modalPos);
+        modal.setModality(Qt::ApplicationModal);
+        modal.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&modal));
+        modal.requestActivate();
+        QVERIFY(QTest::qWaitForWindowActive(&modal));
+
+        QCoreApplication::processEvents();
+        QTRY_COMPARE(root.leaveEventCount, 1);
+
+        root.resetCounters();
+        modal.close();
+
+        // Check for the enter event
+        QTRY_COMPARE(root.enterEventCount, 1);
+    }
+}
+#endif
+
 class ColoredWindow : public QRasterWindow {
 public:
     explicit ColoredWindow(const QColor &color, QWindow *parent = 0) : 
QRasterWindow(parent), m_color(color) {}
-- 
2.6.6

++++++ 0008-xcb-resourceType-names-must-have-only-small-letters.patch ++++++
>From e467aba779546f73f8308838071fe7da00d2ec7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spa...@wp.pl>
Date: Thu, 3 Mar 2016 01:43:41 +0100
Subject: [PATCH 08/16] xcb: resourceType names must have only small letters

Change-Id: I563ae26c9e7e6111399fd0b9af7bfb3ff750b34a
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit caa82c3518b4a5c09b1de990874190d5d765656f)
---
 src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp 
b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 
dfb0a125e25ea72c6a9f5aaf3e3145a2eb3efbeb..f6bd878bde4ef1b659fc22d357a691e5ae6bfc71
 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -76,7 +76,7 @@ static int resourceType(const QByteArray &key)
         QByteArrayLiteral("startupid"), QByteArrayLiteral("traywindow"),
         QByteArrayLiteral("gettimestamp"), QByteArrayLiteral("x11screen"),
         QByteArrayLiteral("rootwindow"),
-        QByteArrayLiteral("subpixeltype"), 
QByteArrayLiteral("antialiasingEnabled"),
+        QByteArrayLiteral("subpixeltype"), 
QByteArrayLiteral("antialiasingenabled"),
         QByteArrayLiteral("nofonthinting"),
         QByteArrayLiteral("atspibus")
     };
-- 
2.6.6

++++++ 0009-Expose-the-number-of-X-screen-through-the-QXcbScreen.patch ++++++
>From fd6049144e0ba5b4696798eadd84da021438d050 Mon Sep 17 00:00:00 2001
From: Alexander Volkov <a.vol...@rusbitech.ru>
Date: Thu, 10 Sep 2015 14:44:52 +0300
Subject: [PATCH 09/16] Expose the number of X screen through the
 QXcbScreenFunctions

X screen corresponds to Qt virtual desktop, and RandR output
corresponds to QScreen. There can be more than one X screen,
so we need a way to get the number of X screen for QScreen,
in particular for the right implementation of some methods
in QX11Info.

Change-Id: Ib5e38703bf11ae08bb283f26a7b7b15f1a5e8671
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit 362b977e7c99d47c9c598cef946273089881fd81)
---
 .../xcbfunctions/qxcbscreenfunctions.h             | 56 ++++++++++++++++++++++
 src/platformheaders/xcbfunctions/xcbfunctions.pri  |  3 +-
 src/plugins/platforms/xcb/qxcbnativeinterface.cpp  |  5 ++
 src/plugins/platforms/xcb/qxcbscreen.cpp           |  8 ++++
 src/plugins/platforms/xcb/qxcbscreen.h             |  1 +
 5 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 src/platformheaders/xcbfunctions/qxcbscreenfunctions.h

diff --git a/src/platformheaders/xcbfunctions/qxcbscreenfunctions.h 
b/src/platformheaders/xcbfunctions/qxcbscreenfunctions.h
new file mode 100644
index 
0000000000000000000000000000000000000000..7773c275b9d6d6bacbf776d13cbb5a5ccbcf2bbf
--- /dev/null
+++ b/src/platformheaders/xcbfunctions/qxcbscreenfunctions.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBSCREENFUNCTIONS_H
+#define QXCBSCREENFUNCTIONS_H
+
+#include <QtPlatformHeaders/QPlatformHeaderHelper>
+
+QT_BEGIN_NAMESPACE
+
+class QScreen;
+
+class QXcbScreenFunctions
+{
+public:
+    typedef bool (*VirtualDesktopNumber)(const QScreen *screen);
+    static const QByteArray virtualDesktopNumberIdentifier() { return 
QByteArrayLiteral("XcbVirtualDesktopNumber"); }
+    static int virtualDesktopNumber(const QScreen *screen)
+    {
+        return QPlatformHeaderHelper::callPlatformFunction<int, 
VirtualDesktopNumber, const QScreen *>(virtualDesktopNumberIdentifier(), 
screen);
+    }
+};
+
+QT_END_NAMESPACE
+
+#endif  /*QXCBSCREENFUNCTIONS_H*/
diff --git a/src/platformheaders/xcbfunctions/xcbfunctions.pri 
b/src/platformheaders/xcbfunctions/xcbfunctions.pri
index 
7f611d80bd5518b1e018a4738c0da79d814d2f47..3f2bcb2b34cb23e55ad57898b44ff442d66980e3
 100644
--- a/src/platformheaders/xcbfunctions/xcbfunctions.pri
+++ b/src/platformheaders/xcbfunctions/xcbfunctions.pri
@@ -1,3 +1,4 @@
 HEADERS += \
     $$PWD/qxcbwindowfunctions.h \
-    $$PWD/qxcbintegrationfunctions.h
+    $$PWD/qxcbintegrationfunctions.h \
+    $$PWD/qxcbscreenfunctions.h
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp 
b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 
f6bd878bde4ef1b659fc22d357a691e5ae6bfc71..96239a0f2041d901500fd645d6c699a93ceda5c9
 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -48,6 +48,7 @@
 
 #include <QtPlatformHeaders/qxcbwindowfunctions.h>
 #include <QtPlatformHeaders/qxcbintegrationfunctions.h>
+#include <QtPlatformHeaders/qxcbscreenfunctions.h>
 
 #ifndef QT_NO_DBUS
 #include "QtPlatformSupport/private/qdbusmenuconnection_p.h"
@@ -367,6 +368,10 @@ QFunctionPointer 
QXcbNativeInterface::platformFunction(const QByteArray &functio
     if (function == QXcbWindowFunctions::visualIdIdentifier()) {
         return 
QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic));
     }
+
+    if (function == QXcbScreenFunctions::virtualDesktopNumberIdentifier())
+        return 
QFunctionPointer(QXcbScreenFunctions::VirtualDesktopNumber(QXcbScreen::virtualDesktopNumberStatic));
+
     return Q_NULLPTR;
 }
 
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp 
b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 
28b175371264cd445c1bd67a8d33f6de5a8fa219..1a90f824fc454c69f73ac195b1241bc6371d7aed
 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -438,6 +438,14 @@ void QXcbScreen::setOutput(xcb_randr_output_t outputId,
     // TODO: Send an event to the QScreen instance that the screen changed its 
name
 }
 
+int QXcbScreen::virtualDesktopNumberStatic(const QScreen *screen)
+{
+    if (screen && screen->handle())
+        return static_cast<const QXcbScreen 
*>(screen->handle())->screenNumber();
+
+    return 0;
+}
+
 /*!
     \brief handle the XCB screen change event and update properties
 
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h 
b/src/plugins/platforms/xcb/qxcbscreen.h
index 
f4de2b9dfd5e3042f4192b85c8e7b9b79aa04e74..7376ddf35c3b34ef7f5310299039431a9a97d45b
 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -133,6 +133,7 @@ public:
     bool isPrimary() const { return m_primary; }
 
     int screenNumber() const { return m_virtualDesktop->number(); }
+    static int virtualDesktopNumberStatic(const QScreen *screen);
 
     xcb_screen_t *screen() const { return m_virtualDesktop->screen(); }
     xcb_window_t root() const { return screen()->root; }
-- 
2.6.6

++++++ 0010-xcb-mark-mouse-events-from-tablet-devices-as-synthes.patch ++++++
>From c44d853fd7e71eff0e1a1d4512c2215a1e701008 Mon Sep 17 00:00:00 2001
From: Shawn Rutledge <shawn.rutle...@digia.com>
Date: Tue, 8 Mar 2016 15:50:20 +0100
Subject: [PATCH 10/16] xcb: mark mouse events from tablet devices as
 synthesized

Task-number: QTBUG-51617
Change-Id: Ic1d258c56165947ff821b1bf4d044bcf29b41a3b
Reviewed-by: Laszlo Agocs <laszlo.ag...@theqtcompany.com>
(cherry picked from commit d7db6c6c1944894737babf3958d0cff1e6222a22)
---
 src/plugins/platforms/xcb/qxcbconnection.h       |  2 +-
 src/plugins/platforms/xcb/qxcbconnection_xi2.cpp |  2 +-
 src/plugins/platforms/xcb/qxcbwindow.cpp         | 39 +++++++++++++++---------
 src/plugins/platforms/xcb/qxcbwindow.h           | 11 ++++---
 4 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbconnection.h 
b/src/plugins/platforms/xcb/qxcbconnection.h
index 
6c2b8583af24e9abd7a087144fb33504ec36fbf8..4d318457e3b05de8c343580aad217cc1bad9072c
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -348,7 +348,7 @@ public:
     virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {}
     virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t 
*) {}
 #ifdef XCB_USE_XINPUT22
-    virtual void handleXIMouseEvent(xcb_ge_event_t *) {}
+    virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource = 
Qt::MouseEventNotSynthesized) {}
     virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
 #endif
     virtual QXcbWindow *toWindow() { return 0; }
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp 
b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 
0c78c0e0d2bc9d05e9f6768ead72cad4a51d03a7..bf961318a343e56ee4e4a72a854ff757875be534
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -1096,7 +1096,7 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, 
TabletData *tabletData, Q
     // Synthesize mouse events since otherwise there are no mouse events from
     // the pen on the XI 2.2+ path.
     if (xi2MouseEvents() && eventListener)
-        eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t 
*>(event));
+        eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t 
*>(event), Qt::MouseEventSynthesizedByQt);
 #else
     Q_UNUSED(eventListener);
 #endif
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
7eae2d92ab39843d09cb6294f9afd7fc51260ecb..5ed35ec8e2bbc0c29b72fb616a746a352a9df969
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -34,6 +34,7 @@
 #include "qxcbwindow.h"
 
 #include <QtDebug>
+#include <QMetaEnum>
 #include <QScreen>
 #include <QtGui/QIcon>
 #include <QtGui/QRegion>
@@ -2157,7 +2158,7 @@ void QXcbWindow::handleUnmapNotifyEvent(const 
xcb_unmap_notify_event_t *event)
 }
 
 void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, 
int root_y,
-                                        int detail, Qt::KeyboardModifiers 
modifiers, xcb_timestamp_t timestamp)
+                                        int detail, Qt::KeyboardModifiers 
modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source)
 {
     const bool isWheel = detail >= 4 && detail <= 7;
     if (!isWheel && window() != QGuiApplication::focusWindow()) {
@@ -2193,11 +2194,11 @@ void QXcbWindow::handleButtonPressEvent(int event_x, 
int event_y, int root_x, in
         return;
     }
 
-    handleMouseEvent(timestamp, local, global, modifiers);
+    handleMouseEvent(timestamp, local, global, modifiers, source);
 }
 
 void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int 
root_x, int root_y,
-                                          int detail, Qt::KeyboardModifiers 
modifiers, xcb_timestamp_t timestamp)
+                                          int detail, Qt::KeyboardModifiers 
modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source)
 {
     QPoint local(event_x, event_y);
     QPoint global(root_x, root_y);
@@ -2207,7 +2208,7 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, 
int event_y, int root_x,
         return;
     }
 
-    handleMouseEvent(timestamp, local, global, modifiers);
+    handleMouseEvent(timestamp, local, global, modifiers, source);
 }
 
 static bool ignoreLeaveEvent(quint8 mode, quint8 detail)
@@ -2290,11 +2291,11 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int 
root_y,
 }
 
 void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, 
int root_y,
-                                         Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp)
+                                         Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp, Qt::MouseEventSource source)
 {
     QPoint local(event_x, event_y);
     QPoint global(root_x, root_y);
-    handleMouseEvent(timestamp, local, global, modifiers);
+    handleMouseEvent(timestamp, local, global, modifiers, source);
 }
 
 // Handlers for plain xcb events. Used only when XI 2.2 or newer is not 
available.
@@ -2325,7 +2326,7 @@ static inline int fixed1616ToInt(FP1616 val)
 }
 
 // With XI 2.2+ press/release/motion comes here instead of the above handlers.
-void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
+void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, 
Qt::MouseEventSource source)
 {
     QXcbConnection *conn = connection();
     xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event);
@@ -2345,20 +2346,27 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t 
*event)
             conn->setButton(conn->translateMouseButton(i), 
XIMaskIsSet(buttonMask, i));
     }
 
+    const char *sourceName = nullptr;
+    if (lcQpaXInput().isDebugEnabled()) {
+        const QMetaObject *metaObject = qt_getEnumMetaObject(source);
+        const QMetaEnum me = 
metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(source)));
+        sourceName = me.valueToKey(source);
+    }
+
     switch (ev->evtype) {
     case XI_ButtonPress:
-        qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d", button, 
ev->time);
+        qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d, source %s", 
button, ev->time, sourceName);
         conn->setButton(button, true);
-        handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, 
modifiers, ev->time);
+        handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, 
modifiers, ev->time, source);
         break;
     case XI_ButtonRelease:
-        qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d", button, 
ev->time);
+        qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d, source 
%s", button, ev->time, sourceName);
         conn->setButton(button, false);
-        handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, 
modifiers, ev->time);
+        handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, 
modifiers, ev->time, source);
         break;
     case XI_Motion:
-        qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d", event_x, 
event_y, ev->time);
-        handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, 
ev->time);
+        qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d, source %s", 
event_x, event_y, ev->time, sourceName);
+        handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, 
ev->time, source);
         break;
     default:
         qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
@@ -2401,10 +2409,11 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t 
*event)
 
 QXcbWindow *QXcbWindow::toWindow() { return this; }
 
-void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, 
const QPoint &global, Qt::KeyboardModifiers modifiers)
+void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, 
const QPoint &global,
+        Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source)
 {
     connection()->setTime(time);
-    QWindowSystemInterface::handleMouseEvent(window(), time, local, global, 
connection()->buttons(), modifiers);
+    QWindowSystemInterface::handleMouseEvent(window(), time, local, global, 
connection()->buttons(), modifiers, source);
 }
 
 void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h 
b/src/plugins/platforms/xcb/qxcbwindow.h
index 
69790f29ae098bbfcc5aa6edec75e3d0fea8ea75..4673f3dd33fd5cc9aa12bc1c50244b84ee3e398e
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -133,13 +133,14 @@ public:
     void handleFocusOutEvent(const xcb_focus_out_event_t *event) 
Q_DECL_OVERRIDE;
     void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) 
Q_DECL_OVERRIDE;
 #ifdef XCB_USE_XINPUT22
-    void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE;
+    void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource source = 
Qt::MouseEventNotSynthesized) Q_DECL_OVERRIDE;
     void handleXIEnterLeave(xcb_ge_event_t *) Q_DECL_OVERRIDE;
 #endif
 
     QXcbWindow *toWindow() Q_DECL_OVERRIDE;
 
-    void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const 
QPoint &global, Qt::KeyboardModifiers modifiers);
+    void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const 
QPoint &global,
+                          Qt::KeyboardModifiers modifiers, 
Qt::MouseEventSource source);
 
     void updateNetWmUserTime(xcb_timestamp_t timestamp);
 
@@ -207,13 +208,13 @@ protected:
     bool compressExposeEvent(QRegion &exposeRegion);
 
     void handleButtonPressEvent(int event_x, int event_y, int root_x, int 
root_y,
-                                int detail, Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp);
+                                int detail, Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp, Qt::MouseEventSource source = 
Qt::MouseEventNotSynthesized);
 
     void handleButtonReleaseEvent(int event_x, int event_y, int root_x, int 
root_y,
-                                  int detail, Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp);
+                                  int detail, Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp, Qt::MouseEventSource source = 
Qt::MouseEventNotSynthesized);
 
     void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int 
root_y,
-                                 Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp);
+                                 Qt::KeyboardModifiers modifiers, 
xcb_timestamp_t timestamp, Qt::MouseEventSource source = 
Qt::MouseEventNotSynthesized);
 
     void handleEnterNotifyEvent(int event_x, int event_y, int root_x, int 
root_y,
                                 quint8 mode, quint8 detail, xcb_timestamp_t 
timestamp);
-- 
2.6.6

++++++ 0011-xcb-Initialize-all-xcb_client_message_event_t-member.patch ++++++
>From 3c8b9236ed7a0b1284922097da875cc8baa1bb78 Mon Sep 17 00:00:00 2001
From: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
Date: Mon, 14 Mar 2016 10:07:20 +0100
Subject: [PATCH 11/16] xcb: Initialize all xcb_client_message_event_t members
 before use

Change-Id: I01e4b69b138fd19fc7e67751d93adebc1326b2f9
Reviewed-by: Orgad Shaneh <org...@gmail.com>
(cherry picked from commit 6c53f2528c86fb72f19951a799f0afaa02ad4490)
---
 src/plugins/platforms/xcb/qxcbdrag.cpp              | 6 ++++++
 src/plugins/platforms/xcb/qxcbscreen.cpp            | 1 +
 src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp | 2 +-
 src/plugins/platforms/xcb/qxcbwindow.cpp            | 5 +++++
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp 
b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 
aa6445d2da56f09696c98cba76baf6c74e44841c..f5cc87394b941014a1f45e0064d341dc8ad093d0
 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -423,6 +423,7 @@ void QXcbDrag::move(const QPoint &globalPos)
 
             xcb_client_message_event_t enter;
             enter.response_type = XCB_CLIENT_MESSAGE;
+            enter.sequence = 0;
             enter.window = target;
             enter.format = 32;
             enter.type = atom(QXcbAtom::XdndEnter);
@@ -451,6 +452,7 @@ void QXcbDrag::move(const QPoint &globalPos)
 
         xcb_client_message_event_t move;
         move.response_type = XCB_CLIENT_MESSAGE;
+        move.sequence = 0;
         move.window = target;
         move.format = 32;
         move.type = atom(QXcbAtom::XdndPosition);
@@ -479,6 +481,7 @@ void QXcbDrag::drop(const QPoint &globalPos)
 
     xcb_client_message_event_t drop;
     drop.response_type = XCB_CLIENT_MESSAGE;
+    drop.sequence = 0;
     drop.window = current_target;
     drop.format = 32;
     drop.type = atom(QXcbAtom::XdndDrop);
@@ -740,6 +743,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, 
const xcb_client_message
 
     xcb_client_message_event_t response;
     response.response_type = XCB_CLIENT_MESSAGE;
+    response.sequence = 0;
     response.window = xdnd_dragsource;
     response.format = 32;
     response.type = atom(QXcbAtom::XdndStatus);
@@ -886,6 +890,7 @@ void QXcbDrag::send_leave()
 
     xcb_client_message_event_t leave;
     leave.response_type = XCB_CLIENT_MESSAGE;
+    leave.sequence = 0;
     leave.window = current_target;
     leave.format = 32;
     leave.type = atom(QXcbAtom::XdndLeave);
@@ -956,6 +961,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const 
xcb_client_message_event_t *e
 
     xcb_client_message_event_t finished;
     finished.response_type = XCB_CLIENT_MESSAGE;
+    finished.sequence = 0;
     finished.window = xdnd_dragsource;
     finished.format = 32;
     finished.type = atom(QXcbAtom::XdndFinished);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp 
b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 
1a90f824fc454c69f73ac195b1241bc6371d7aed..f74244e13c852d4a4844bb6e470d037e03a45c84
 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -361,6 +361,7 @@ void QXcbScreen::sendStartupMessage(const QByteArray 
&message) const
     ev.response_type = XCB_CLIENT_MESSAGE;
     ev.format = 8;
     ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO_BEGIN);
+    ev.sequence = 0;
     ev.window = rootWindow;
     int sent = 0;
     int length = message.length() + 1; // include NUL byte
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp 
b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index 
1f217e8de798d5161ec52bf8e88508f7314e6328..49c0440a3c4b48e2abaff5515cc4341257bcbc88
 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -94,9 +94,9 @@ xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const 
QXcbConnection *conne
 void QXcbSystemTrayTracker::requestSystemTrayWindowDock(xcb_window_t window) 
const
 {
     xcb_client_message_event_t trayRequest;
-    memset(&trayRequest, 0, sizeof(trayRequest));
     trayRequest.response_type = XCB_CLIENT_MESSAGE;
     trayRequest.format = 32;
+    trayRequest.sequence = 0;
     trayRequest.window = m_trayWindow;
     trayRequest.type = m_trayAtom;
     trayRequest.data.data32[0] = XCB_CURRENT_TIME;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
5ed35ec8e2bbc0c29b72fb616a746a352a9df969..1dc066c692d5beaf632ead78784683c928d1c1e4
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1224,6 +1224,7 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t 
one, xcb_atom_t two)
 
     event.response_type = XCB_CLIENT_MESSAGE;
     event.format = 32;
+    event.sequence = 0;
     event.window = m_window;
     event.type = atom(QXcbAtom::_NET_WM_STATE);
     event.data.data32[0] = set ? 1 : 0;
@@ -1265,6 +1266,7 @@ void QXcbWindow::setWindowState(Qt::WindowState state)
 
             event.response_type = XCB_CLIENT_MESSAGE;
             event.format = 32;
+            event.sequence = 0;
             event.window = m_window;
             event.type = atom(QXcbAtom::WM_CHANGE_STATE);
             event.data.data32[0] = XCB_WM_STATE_ICONIC;
@@ -1660,6 +1662,7 @@ void QXcbWindow::requestActivateWindow()
 
         event.response_type = XCB_CLIENT_MESSAGE;
         event.format = 32;
+        event.sequence = 0;
         event.window = m_window;
         event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
         event.data.data32[0] = 1;
@@ -2607,6 +2610,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, 
Qt::Corner corner)
     xcb_client_message_event_t xev;
     xev.response_type = XCB_CLIENT_MESSAGE;
     xev.type = moveResize;
+    xev.sequence = 0;
     xev.window = xcb_window();
     xev.format = 32;
     const QPoint globalPos = window()->mapToGlobal(pos);
@@ -2635,6 +2639,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, 
quint32 message,
 
     event.response_type = XCB_CLIENT_MESSAGE;
     event.format = 32;
+    event.sequence = 0;
     event.window = window;
     event.type = atom(QXcbAtom::_XEMBED);
     event.data.data32[0] = connection()->time();
-- 
2.6.6

++++++ 0012-xcb-Merge-_NET_WM_STATE-hints-instead-of-overwriting.patch ++++++
>From cc32b65569c3cd947a7d012d41379490c9bf80c0 Mon Sep 17 00:00:00 2001
From: David Rosca <now...@gmail.com>
Date: Wed, 16 Mar 2016 08:35:22 +0100
Subject: [PATCH 12/16] xcb: Merge _NET_WM_STATE hints instead of overwriting

This makes possible to set custom _NET_WM_STATE hints before
showing the window.

Change-Id: I86ad3863f7a8b3bb610a31b9af4b02c9d38eb111
Task-number: QTBUG-26978
Reviewed-by: Ilya Kotov
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
Reviewed-by: Uli Schlachter <psyc...@znc.in>
(cherry picked from commit e4cea305ed2ba3c9f580bf9d16c59a1048af0e8a)
---
 src/plugins/platforms/xcb/qxcbwindow.cpp | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
1dc066c692d5beaf632ead78784683c928d1c1e4..d2475a8b1329dee1034f5ac5e054e5318ca2ea09
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1091,21 +1091,37 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
 void QXcbWindow::setNetWmStates(NetWmStates states)
 {
     QVector<xcb_atom_t> atoms;
-    if (states & NetWmStateAbove)
+
+    xcb_get_property_cookie_t get_cookie =
+        xcb_get_property_unchecked(xcb_connection(), 0, m_window, 
atom(QXcbAtom::_NET_WM_STATE),
+                         XCB_ATOM_ATOM, 0, 1024);
+
+    xcb_get_property_reply_t *reply =
+        xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
+
+    if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && 
reply->value_len > 0) {
+        const xcb_atom_t *data = static_cast<const xcb_atom_t 
*>(xcb_get_property_value(reply));
+        atoms.resize(reply->value_len);
+        memcpy((void *)&atoms.first(), (void *)data, reply->value_len * 
sizeof(xcb_atom_t));
+    }
+
+    free(reply);
+
+    if (states & NetWmStateAbove && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
-    if (states & NetWmStateBelow)
+    if (states & NetWmStateBelow && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
-    if (states & NetWmStateFullScreen)
+    if (states & NetWmStateFullScreen && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
-    if (states & NetWmStateMaximizedHorz)
+    if (states & NetWmStateMaximizedHorz && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
-    if (states & NetWmStateMaximizedVert)
+    if (states & NetWmStateMaximizedVert && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
-    if (states & NetWmStateModal)
+    if (states & NetWmStateModal && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MODAL)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL));
-    if (states & NetWmStateStaysOnTop)
+    if (states & NetWmStateStaysOnTop && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
-    if (states & NetWmStateDemandsAttention)
+    if (states & NetWmStateDemandsAttention && 
!atoms.contains(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
         atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
 
     if (atoms.isEmpty()) {
-- 
2.6.6

++++++ 0013-xcb-Fix-interpretation-of-the-size-from-RRCrtcChange.patch ++++++
>From a148affea7763395ce503f695ddb6c7b4c1e4b08 Mon Sep 17 00:00:00 2001
From: Alexander Volkov <a.vol...@rusbitech.ru>
Date: Fri, 8 Apr 2016 18:50:15 +0300
Subject: [PATCH 13/16] xcb: Fix interpretation of the size from
 RRCrtcChangeNotify
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The size in RRCrtcChangeNotify is a size of the mode and it is
not rotated. At the same time when we call RRGetCrtcInfo, it
returns a rotated size, which is then passed to
QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation).

So to pass the expected size to QXcbScreen::updateGeometry()
after receiving RRCrtcChangeNotify, we should rotate the size
according the screen rotation.

Change-Id: If5b5b52403b077d3cd64b9a05d938bb9ac00b1e0
Reviewed-by: Daniel Vrátil <daniel.vra...@kdab.com>
Reviewed-by: Laszlo Agocs <laszlo.ag...@theqtcompany.com>
(cherry picked from commit d8667fde189fa08002295fc66414d67e73b3c67b)
---
 src/plugins/platforms/xcb/qxcbconnection.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp 
b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 
aeb730670d62b3ce2239fba48b58ccb4752e912d..9f170b095926501b91a20f401284c6c6149a07ab
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -209,6 +209,9 @@ void QXcbConnection::updateScreens(const 
xcb_randr_notify_event_t *event)
         // CRTC with node mode could mean that output has been disabled, and 
we'll
         // get RRNotifyOutputChange notification for that.
         if (screen && crtc.mode) {
+            if (crtc.rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
+                crtc.rotation == XCB_RANDR_ROTATION_ROTATE_270)
+                std::swap(crtc.width, crtc.height);
             screen->updateGeometry(QRect(crtc.x, crtc.y, crtc.width, 
crtc.height), crtc.rotation);
             if (screen->mode() != crtc.mode)
                 screen->updateRefreshRate(crtc.mode);
-- 
2.6.6

++++++ 0014-xcb-Properly-process-enter-leave-events.patch ++++++
>From 123a082fd423422412d554a3b5973bcfc78c62a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spa...@wp.pl>
Date: Thu, 14 Apr 2016 17:00:23 +0200
Subject: [PATCH 14/16] xcb: Properly process enter/leave events

Ignore enter/leave events when there is a window under mouse button.
Unset window under mouse button if other window is grabbed.
Smarter ignoring (un)grab ancestor enter/leave event.
Ignore ungrab inferior leave event.

Amends: b9f76db30d261421e4da58f29053181af04ceb4d

Task-number: QTBUG-46576
Task-number: QTBUG-51573
Task-number: QTBUG-52332
Task-number: QTBUG-52488
Change-Id: I8d926309aa60bb8929728691c31ecf93d1e299ad
Reviewed-by: Dmitry Shachnev <mity...@gmail.com>
Reviewed-by: Laszlo Agocs <laszlo.ag...@theqtcompany.com>
Reviewed-by: Shawn Rutledge <shawn.rutle...@theqtcompany.com>
(cherry picked from commit c511466d747d99ee76465cfe90ce594fa1f27469)
---
 src/plugins/platforms/xcb/qxcbconnection.cpp |  6 +++
 src/plugins/platforms/xcb/qxcbconnection.h   |  3 ++
 src/plugins/platforms/xcb/qxcbwindow.cpp     | 70 ++++++++++++++++++++++------
 3 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp 
b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 
9f170b095926501b91a20f401284c6c6149a07ab..333a9606f50e9c27bdb7d24c836a3029a635b881
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -560,6 +560,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface 
*nativeInterface, bool canGra
     , m_buttons(0)
     , m_focusWindow(0)
     , m_mouseGrabber(0)
+    , m_mousePressWindow(0)
     , m_clientLeader(0)
     , m_systemTrayTracker(0)
     , m_glIntegration(Q_NULLPTR)
@@ -1367,6 +1368,11 @@ void QXcbConnection::setFocusWindow(QXcbWindow *w)
 void QXcbConnection::setMouseGrabber(QXcbWindow *w)
 {
     m_mouseGrabber = w;
+    m_mousePressWindow = Q_NULLPTR;
+}
+void QXcbConnection::setMousePressWindow(QXcbWindow *w)
+{
+    m_mousePressWindow = w;
 }
 
 void QXcbConnection::grabServer()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h 
b/src/plugins/platforms/xcb/qxcbconnection.h
index 
4d318457e3b05de8c343580aad217cc1bad9072c..0c004a86dd286a2c4aaf77d249eef14a2af8ff03
 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -473,6 +473,8 @@ public:
     void setFocusWindow(QXcbWindow *);
     QXcbWindow *mouseGrabber() const { return m_mouseGrabber; }
     void setMouseGrabber(QXcbWindow *);
+    QXcbWindow *mousePressWindow() const { return m_mousePressWindow; }
+    void setMousePressWindow(QXcbWindow *);
 
     QByteArray startupId() const { return m_startupId; }
     void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
@@ -656,6 +658,7 @@ private:
 
     QXcbWindow *m_focusWindow;
     QXcbWindow *m_mouseGrabber;
+    QXcbWindow *m_mousePressWindow;
 
     xcb_window_t m_clientLeader;
     QByteArray m_startupId;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp 
b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 
d2475a8b1329dee1034f5ac5e054e5318ca2ea09..e8ad6be82bba983127ecf0fe2c7f0a951d9b5fb3
 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -616,8 +616,12 @@ QXcbWindow::~QXcbWindow()
 {
     if (window()->type() != Qt::ForeignWindow)
         destroy();
-    else if (connection()->mouseGrabber() == this)
-        connection()->setMouseGrabber(Q_NULLPTR);
+    else {
+        if (connection()->mouseGrabber() == this)
+            connection()->setMouseGrabber(Q_NULLPTR);
+        if (connection()->mousePressWindow() == this)
+            connection()->setMousePressWindow(Q_NULLPTR);
+    }
 }
 
 void QXcbWindow::destroy()
@@ -875,6 +879,16 @@ void QXcbWindow::hide()
 
     if (connection()->mouseGrabber() == this)
         connection()->setMouseGrabber(Q_NULLPTR);
+    if (QPlatformWindow *w = connection()->mousePressWindow()) {
+        // Unset mousePressWindow when it (or one of its parents) is unmapped
+        while (w) {
+            if (w == this) {
+                connection()->setMousePressWindow(Q_NULLPTR);
+                break;
+            }
+            w = w->parent();
+        }
+    }
 
     m_mapped = false;
 
@@ -2213,6 +2227,8 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int 
event_y, int root_x, in
         return;
     }
 
+    connection()->setMousePressWindow(this);
+
     handleMouseEvent(timestamp, local, global, modifiers, source);
 }
 
@@ -2227,19 +2243,44 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, 
int event_y, int root_x,
         return;
     }
 
+    if (connection()->buttons() == Qt::NoButton)
+        connection()->setMousePressWindow(Q_NULLPTR);
+
     handleMouseEvent(timestamp, local, global, modifiers, source);
 }
 
-static bool ignoreLeaveEvent(quint8 mode, quint8 detail)
+static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
+{
+    /* Checking for XCB_NOTIFY_MODE_GRAB and XCB_NOTIFY_DETAIL_ANCESTOR 
prevents unwanted
+     * enter/leave events on AwesomeWM on mouse button press. It also ignores 
duplicated
+     * enter/leave events on Alt+Tab switching on some WMs with XInput2 events.
+     * Without XInput2 events the (Un)grabAncestor cannot be checked when 
mouse button is
+     * not pressed, otherwise (e.g. on Alt+Tab) it can igonre important 
enter/leave events.
+    */
+    if (conn) {
+        const bool mouseButtonsPressed = (conn->buttons() != Qt::NoButton);
+#ifdef XCB_USE_XINPUT22
+        return mouseButtonsPressed || (conn->isAtLeastXI22() && 
conn->xi2MouseEvents());
+#else
+        return mouseButtonsPressed;
+#endif
+    }
+    return true;
+}
+
+static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn 
= Q_NULLPTR)
 {
-    return (mode == XCB_NOTIFY_MODE_GRAB && detail == 
XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
+    return ((doCheckUnGrabAncestor(conn)
+             && mode == XCB_NOTIFY_MODE_GRAB && detail == 
XCB_NOTIFY_DETAIL_ANCESTOR)
+            || (mode == XCB_NOTIFY_MODE_UNGRAB && detail == 
XCB_NOTIFY_DETAIL_INFERIOR)
             || detail == XCB_NOTIFY_DETAIL_VIRTUAL
-            || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL;
+            || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
 }
 
-static bool ignoreEnterEvent(quint8 mode, quint8 detail)
+static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn 
= Q_NULLPTR)
 {
-    return ((mode == XCB_NOTIFY_MODE_UNGRAB && detail == 
XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
+    return ((doCheckUnGrabAncestor(conn)
+             && mode == XCB_NOTIFY_MODE_UNGRAB && detail == 
XCB_NOTIFY_DETAIL_ANCESTOR)
             || (mode != XCB_NOTIFY_MODE_NORMAL && mode != 
XCB_NOTIFY_MODE_UNGRAB)
             || detail == XCB_NOTIFY_DETAIL_VIRTUAL
             || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
@@ -2273,9 +2314,7 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int 
event_y, int root_x, in
 
     const QPoint global = QPoint(root_x, root_y);
 
-    if (ignoreEnterEvent(mode, detail)
-            || (connection()->buttons() != Qt::NoButton
-                && QGuiApplicationPrivate::lastCursorPosition != global))
+    if (ignoreEnterEvent(mode, detail, connection()) || 
connection()->mousePressWindow())
         return;
 
     const QPoint local(event_x, event_y);
@@ -2287,11 +2326,7 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int 
root_y,
 {
     connection()->setTime(timestamp);
 
-    const QPoint global(root_x, root_y);
-
-    if (ignoreLeaveEvent(mode, detail)
-            || (connection()->buttons() != Qt::NoButton
-                && QGuiApplicationPrivate::lastCursorPosition != global))
+    if (ignoreLeaveEvent(mode, detail, connection()) || 
connection()->mousePressWindow())
         return;
 
     EnterEventChecker checker;
@@ -2314,6 +2349,11 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, 
int event_y, int root_x, i
 {
     QPoint local(event_x, event_y);
     QPoint global(root_x, root_y);
+
+    // "mousePressWindow" can be NULL i.e. if a window will be grabbed or 
umnapped, so set it again here
+    if (connection()->buttons() != Qt::NoButton && 
connection()->mousePressWindow() == Q_NULLPTR)
+        connection()->setMousePressWindow(this);
+
     handleMouseEvent(timestamp, local, global, modifiers, source);
 }
 
-- 
2.6.6

++++++ 0015-Use-the-state-of-the-key-event-to-process-it.patch ++++++
>From d7be69c973623e76deff3fa00354927946b21c66 Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <aa...@kde.org>
Date: Thu, 21 Apr 2016 01:39:27 +0200
Subject: [PATCH 15/16] Use the state of the key event to process it

Use the state of the key event instead of the global state.
UpdateXKBStateFromState uses xkbModMask, which needs updateXKBMods
to be called beforehand.

Task-number: QTBUG-48795
Change-Id: Ic2c545718adb68df41730e5a3bf25adb374ffce3
---
 src/plugins/platforms/xcb/qxcbkeyboard.cpp | 72 ++++++++++++++++++------------
 src/plugins/platforms/xcb/qxcbkeyboard.h   |  2 +
 2 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp 
b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 
631dd17908f458533f413409773b6c078b743d98..baba7ec812c16025893bf5267fba545e8b4378bf
 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -742,8 +742,7 @@ void QXcbKeyboard::updateKeymap()
     // update xkb state object
     xkb_state_unref(xkb_state);
     xkb_state = new_state;
-    if (!connection()->hasXKB())
-        updateXKBMods();
+    updateXKBMods();
 
     checkForLatinLayout();
 }
@@ -768,32 +767,37 @@ void 
QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
 }
 #endif
 
+void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 
state)
+{
+    const quint32 modsDepressed = xkb_state_serialize_mods(kb_state, 
XKB_STATE_MODS_DEPRESSED);
+    const quint32 modsLatched = xkb_state_serialize_mods(kb_state, 
XKB_STATE_MODS_LATCHED);
+    const quint32 modsLocked = xkb_state_serialize_mods(kb_state, 
XKB_STATE_MODS_LOCKED);
+    const quint32 xkbMask = xkbModMask(state);
+
+    const quint32 latched = modsLatched & xkbMask;
+    const quint32 locked = modsLocked & xkbMask;
+    quint32 depressed = modsDepressed & xkbMask;
+    // set modifiers in depressed if they don't appear in any of the final 
masks
+    depressed |= ~(depressed | latched | locked) & xkbMask;
+
+    const xkb_state_component newState
+            = xkb_state_update_mask(kb_state,
+                            depressed,
+                            latched,
+                            locked,
+                            0,
+                            0,
+                            (state >> 13) & 3); // bits 13 and 14 report the 
state keyboard group
+
+    if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) 
{
+        //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
+    }
+}
+
 void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
 {
     if (m_config && !connection()->hasXKB()) {
-        const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, 
XKB_STATE_MODS_DEPRESSED);
-        const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, 
XKB_STATE_MODS_LATCHED);
-        const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, 
XKB_STATE_MODS_LOCKED);
-        const quint32 xkbMask = xkbModMask(state);
-
-        const quint32 latched = modsLatched & xkbMask;
-        const quint32 locked = modsLocked & xkbMask;
-        quint32 depressed = modsDepressed & xkbMask;
-        // set modifiers in depressed if they don't appear in any of the final 
masks
-        depressed |= ~(depressed | latched | locked) & xkbMask;
-
-        const xkb_state_component newState
-                = xkb_state_update_mask(xkb_state,
-                              depressed,
-                              latched,
-                              locked,
-                              0,
-                              0,
-                              (state >> 13) & 3); // bits 13 and 14 report the 
state keyboard group
-
-        if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == 
XKB_STATE_LAYOUT_EFFECTIVE) {
-            //qWarning("TODO: Support KeyboardLayoutChange on QPA 
(QTBUG-27681)");
-        }
+        updateXKBStateFromState(xkb_state, state);
     }
 }
 
@@ -1445,7 +1449,16 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t 
sourceWindow, QEvent::Type type,
     if (type == QEvent::KeyPress)
         targetWindow->updateNetWmUserTime(time);
 
-    xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code);
+    // Have a temporary keyboard state filled in from state
+    // this way we allow for synthetic events to have different state
+    // from the current state i.e. you can have Alt+Ctrl pressed
+    // and receive a synthetic key event that has neither Alt nor Ctrl pressed
+    struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
+    if (!kb_state)
+        return;
+    updateXKBStateFromState(kb_state, state);
+
+    xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
 
     QPlatformInputContext *inputContext = 
QGuiApplicationPrivate::platformIntegration()->inputContext();
     QMetaMethod method;
@@ -1464,11 +1477,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t 
sourceWindow, QEvent::Type type,
                       Q_ARG(uint, code),
                       Q_ARG(uint, state),
                       Q_ARG(bool, type == QEvent::KeyPress));
-        if (retval)
+        if (retval) {
+            xkb_state_unref(kb_state);
             return;
+        }
     }
 
-    QString string = lookupString(xkb_state, code);
+    QString string = lookupString(kb_state, code);
 
     // Ιf control modifier is set we should prefer latin character, this is
     // used for standard shortcuts in checks like "key == QKeySequence::Copy",
@@ -1537,6 +1552,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t 
sourceWindow, QEvent::Type type,
             QWindowSystemInterface::handleExtendedKeyEvent(window, time, 
QEvent::KeyPress, qtcode, modifiers,
                                                            code, sym, state, 
string, isAutoRepeat);
     }
+    xkb_state_unref(kb_state);
 }
 
 QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t 
code) const
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h 
b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 
457a27affb166e2a3e54c78761361ff3713a4d18..dc27511b56e98bfc0f642e03c0b3aa8b2f4778e9
 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -98,6 +98,8 @@ protected:
     void checkForLatinLayout();
 
 private:
+    void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
+
     bool m_config;
     xcb_keycode_t m_autorepeat_code;
 
-- 
2.6.6

++++++ 0016-xcb-Fix-drag-and-drop-to-applications-like-Emacs-and.patch ++++++
>From 7c3b3375b2d54ef1965c32131123a9becfa27f98 Mon Sep 17 00:00:00 2001
From: Urs Fleisch <uflei...@users.sourceforge.net>
Date: Fri, 26 Feb 2016 17:46:09 +0100
Subject: [PATCH 16/16] xcb: Fix drag and drop to applications like Emacs and
 Chromium.

Drops without matching time stamp do not work. I have fixed the issue by
reanimating the findXdndAwareParent() function (adapted to XCB) and
using it to find a matching transaction if all else fails.

Task-number: QTBUG-45812
Change-Id: Ibca15bbab02ccf2f25280418e9edf36972ebf9a0
---
 src/plugins/platforms/xcb/qxcbdrag.cpp | 55 +++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 11 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp 
b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 
f5cc87394b941014a1f45e0064d341dc8ad093d0..f1428d0a9632bd692ceaa130be58992f282d3081
 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -1072,6 +1072,40 @@ void QXcbDrag::cancel()
         send_leave();
 }
 
+// find an ancestor with XdndAware on it
+static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
+{
+    xcb_window_t target = 0;
+    forever {
+        // check if window has XdndAware
+        xcb_get_property_cookie_t gpCookie = Q_XCB_CALL(
+            xcb_get_property(c->xcb_connection(), false, window,
+                             c->atom(QXcbAtom::XdndAware), 
XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
+        xcb_get_property_reply_t *gpReply = xcb_get_property_reply(
+            c->xcb_connection(), gpCookie, 0);
+        bool aware = gpReply && gpReply->type != XCB_NONE;
+        free(gpReply);
+        if (aware) {
+            target = window;
+            break;
+        }
+
+        // try window's parent
+        xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL(
+            xcb_query_tree_unchecked(c->xcb_connection(), window));
+        xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply(
+            c->xcb_connection(), qtCookie, NULL);
+        if (!qtReply)
+            break;
+        xcb_window_t root = qtReply->root;
+        xcb_window_t parent = qtReply->parent;
+        free(qtReply);
+        if (window == root)
+            break;
+        window = parent;
+    }
+    return target;
+}
 
 void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t 
*event)
 {
@@ -1099,17 +1133,16 @@ void QXcbDrag::handleSelectionRequest(const 
xcb_selection_request_event_t *event
             // xcb_convert_selection() that we sent the XdndDrop event to.
             at = findTransactionByWindow(event->requestor);
         }
-//        if (at == -1 && event->time == XCB_CURRENT_TIME) {
-//            // previous Qt versions always requested the data on a child of 
the target window
-//            // using CurrentTime... but it could be asking for either drop 
data or the current drag's data
-//            Window target = findXdndAwareParent(event->requestor);
-//            if (target) {
-//                if (current_target && current_target == target)
-//                    at = -2;
-//                else
-//                    at = findXdndDropTransactionByWindow(target);
-//            }
-//        }
+
+        if (at == -1 && event->time == XCB_CURRENT_TIME) {
+            xcb_window_t target = findXdndAwareParent(connection(), 
event->requestor);
+            if (target) {
+                if (current_target == target)
+                    at = -2;
+                else
+                    at = findTransactionByWindow(target);
+            }
+        }
     }
 
     QDrag *transactionDrag = 0;
-- 
2.6.6

++++++ Fix-QtDBus-deadlock-inside-kded-kiod.patch ++++++
>From f328f0cd2eb6be2a0a0d148bd769d51eae42bdc6 Mon Sep 17 00:00:00 2001
From: Thiago Macieira <thiago.macie...@intel.com>
Date: Tue, 15 Mar 2016 11:00:20 -0700
Subject: [PATCH] Fix QtDBus deadlock inside kded/kiod

Whenever a message spy was installed, we failed to actually process
looped-back messages by queueing them for processing by the spy. That
had as a consequence that the caller got an error reply and the message,
later, we attempted to deliver the message. Since that message still was
isLocal==true, bad things happened inside the manager thread.

The correct solution is not to queue the message for the filter. If the
message is local, then simply deliver directly, as we're still in the
user's thread. This used to be the behavior in Qt 5.5.

Task-number: QTBUG-51676
Change-Id: I1dc112894cde7121e8ce302ae51b438ade1ff612
---
 src/dbus/qdbusintegrator.cpp | 42 ++++++++++++++++++++++++++++++++----------
 src/dbus/qdbusintegrator_p.h |  1 +
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index cd44861..478a2c4 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -481,6 +481,11 @@ QDBusSpyCallEvent::~QDBusSpyCallEvent()
 
 void QDBusSpyCallEvent::placeMetaCall(QObject *)
 {
+    invokeSpyHooks(msg, hooks, hookCount);
+}
+
+inline void QDBusSpyCallEvent::invokeSpyHooks(const QDBusMessage &msg, const 
Hook *hooks, int hookCount)
+{
     // call the spy hook list
     for (int i = 0; i < hookCount; ++i)
         hooks[i](msg);
@@ -509,7 +514,12 @@ bool QDBusConnectionPrivate::handleMessage(const 
QDBusMessage &amsg)
 {
     if (!ref.load())
         return false;
-    if (!dispatchEnabled && !QDBusMessagePrivate::isLocal(amsg)) {
+
+    // local message are always delivered, regardless of filtering
+    // or whether the dispatcher is enabled
+    bool isLocal = QDBusMessagePrivate::isLocal(amsg);
+
+    if (!dispatchEnabled && !isLocal) {
         // queue messages only, we'll handle them later
         qDBusDebug() << this << "delivery is suspended";
         pendingMessages << amsg;
@@ -523,13 +533,23 @@ bool QDBusConnectionPrivate::handleMessage(const 
QDBusMessage &amsg)
         // let them see the signal too
         return false;
     case QDBusMessage::MethodCallMessage:
-        // run it through the spy filters (if any) before the regular 
processing
+        // run it through the spy filters (if any) before the regular 
processing:
+        // a) if it's a local message, we're in the caller's thread, so invoke 
the filter directly
+        // b) if it's an external message, post to the main thread
         if (Q_UNLIKELY(qDBusSpyHookList.exists()) && qApp) {
             const QDBusSpyHookList &list = *qDBusSpyHookList;
-            qDBusDebug() << this << "invoking message spies";
-            QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, 
QDBusConnection(this),
-                                                                    amsg, 
list.constData(), list.size()));
-            return true;
+            if (isLocal) {
+                Q_ASSERT(QThread::currentThread() != thread());
+                qDBusDebug() << this << "invoking message spies directly";
+                QDBusSpyCallEvent::invokeSpyHooks(amsg, list.constData(), 
list.size());
+            } else {
+                qDBusDebug() << this << "invoking message spies via event";
+                QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, 
QDBusConnection(this),
+                                                                        amsg, 
list.constData(), list.size()));
+
+                // we'll be called back, so return
+                return true;
+            }
         }
 
         handleObjectCall(amsg);
@@ -1451,9 +1471,9 @@ void QDBusConnectionPrivate::handleObjectCall(const 
QDBusMessage &msg)
     // that means the dispatchLock mutex is locked
     // must not call out to user code in that case
     //
-    // however, if the message is internal, handleMessage was called
-    // directly and no lock is in place. We can therefore call out to
-    // user code, if necessary
+    // however, if the message is internal, handleMessage was called directly
+    // (user's thread) and no lock is in place. We can therefore call out to
+    // user code, if necessary.
     ObjectTreeNode result;
     int usedLength;
     QThread *objThread = 0;
@@ -1492,12 +1512,14 @@ void QDBusConnectionPrivate::handleObjectCall(const 
QDBusMessage &msg)
                                                            usedLength, msg));
             return;
         } else if (objThread != QThread::currentThread()) {
-            // synchronize with other thread
+            // looped-back message, targeting another thread:
+            // synchronize with it
             postEventToThread(HandleObjectCallPostEventAction, result.obj,
                               new 
QDBusActivateObjectEvent(QDBusConnection(this), this, result,
                                                            usedLength, msg, 
&sem));
             semWait = true;
         } else {
+            // looped-back message, targeting current thread
             semWait = false;
         }
     } // release the lock
diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h
index 2bbebdf..c0d9c22 100644
--- a/src/dbus/qdbusintegrator_p.h
+++ b/src/dbus/qdbusintegrator_p.h
@@ -145,6 +145,7 @@ public:
     {}
     ~QDBusSpyCallEvent();
     void placeMetaCall(QObject *) Q_DECL_OVERRIDE;
+    static inline void invokeSpyHooks(const QDBusMessage &msg, const Hook 
*hooks, int hookCount);
 
     QDBusConnection conn;   // keeps the refcount in QDBusConnectionPrivate up
     QDBusMessage msg;
-- 
2.6.2.2.g1b5ffa3
++++++ QtDBus-clean-up-signal-hooks-and-object-tree-in-closeConnection.patch 
++++++
>From b024fbe83863fc57364a52c717d5b43d654bdb5d Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wen...@gmail.com>
Date: Sat, 5 Mar 2016 12:23:21 -0800
Subject: [PATCH] QtDBus: clean up signal hooks and object tree in
 closeConnection

If a QObject is added or passed as receiver to QDBusConnection::connect()
and it is managed by Q_GLOBAL_STATIC or similar mechanism, it is
possible that when that its destructor is called after the dbus daemon
thread ends. In that case, QObject::destroyed connected via
Qt::BlockingQueuedConnection to QDBusConnectionPrivate will cause dead
lock since the thread is no longer processing events.

Task-number: QTBUG-51648
Change-Id: I1a1810a6d6d0234af0269d5f3fc1f54101bf1547
---
 src/dbus/qdbusconnection_p.h |  1 +
 src/dbus/qdbusintegrator.cpp | 28 +++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index c77daf7..565eb83 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -254,6 +254,7 @@ private:
                      const QVector<int> &metaTypes, int slotIdx);
 
     SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator 
it);
+    void disconnectObjectTree(ObjectTreeNode &node);
 
     bool isServiceRegisteredByThread(const QString &serviceName);
 
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index cd44861..a3cd47b 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -1030,7 +1030,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
                  qPrintable(name));
 
     closeConnection();
-    rootNode.children.clear();  // free resources
     qDeleteAll(cachedMetaObjects);
 
     if (mode == ClientMode || mode == PeerMode) {
@@ -1052,6 +1051,20 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
     }
 }
 
+void 
QDBusConnectionPrivate::disconnectObjectTree(QDBusConnectionPrivate::ObjectTreeNode
 &haystack)
+{
+    QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = 
haystack.children.begin();
+
+    while (it != haystack.children.end()) {
+        disconnectObjectTree(*it);
+        it++;
+    }
+
+    if (haystack.obj) {
+        haystack.obj->disconnect(this);
+    }
+}
+
 void QDBusConnectionPrivate::closeConnection()
 {
     QDBusWriteLocker locker(CloseConnectionAction, this);
@@ -1075,6 +1088,19 @@ void QDBusConnectionPrivate::closeConnection()
     }
 
     qDeleteAll(pendingCalls);
+
+    // clean up all signal hook and object tree, to avoid QObject::destroyed
+    // being activated to dbus daemon thread which already quits.
+    // dbus connection is already closed, so there is nothing we could do be 
clean
+    // up everything here.
+    SignalHookHash::iterator sit = signalHooks.begin();
+    while (sit != signalHooks.end()) {
+        sit.value().obj->disconnect(this);
+        sit++;
+    }
+
+    disconnectObjectTree(rootNode);
+    rootNode.children.clear();  // free resources
 }
 
 void QDBusConnectionPrivate::checkThread()
-- 
2.6.2.2.g1b5ffa3
++++++ QtDBus-finish-all-pending-call-with-error-if-disconnected.patch ++++++
>From acde2e69df5dedc624674107596f276125e22864 Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wen...@gmail.com>
Date: Thu, 3 Mar 2016 21:56:53 -0800
Subject: [PATCH] QtDBus: finish all pending call with error if disconnected

libdbus will send a local signal if connection gets disconnected. When
this happens, end all pending calls with QDBusError::Disconnected.

Task-number: QTBUG-51649
Change-Id: I5c7d2a468bb5da746d0c0e53e458c1e376f186a9
---
 src/dbus/dbus_minimal_p.h                          |  2 ++
 src/dbus/qdbusintegrator.cpp                       | 26 +++++++++++++++++-----
 src/dbus/qdbusutil_p.h                             |  6 +++++
 .../dbus/qdbusconnection/tst_qdbusconnection.cpp   | 22 ++++++++++++++++++
 .../dbus/qdbusconnection/tst_qdbusconnection.h     |  1 +
 5 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/src/dbus/dbus_minimal_p.h b/src/dbus/dbus_minimal_p.h
index f0a2954..8f25b24 100644
--- a/src/dbus/dbus_minimal_p.h
+++ b/src/dbus/dbus_minimal_p.h
@@ -99,9 +99,11 @@ typedef dbus_uint32_t  dbus_bool_t;
 /* dbus-shared.h */
 #define DBUS_SERVICE_DBUS      "org.freedesktop.DBus"
 #define DBUS_PATH_DBUS  "/org/freedesktop/DBus"
+#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local"
 #define DBUS_INTERFACE_DBUS           "org.freedesktop.DBus"
 #define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
 #define DBUS_INTERFACE_PROPERTIES     "org.freedesktop.DBus.Properties"
+#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local"
 
 #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to 
become the primary owner if requested */
 #define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the 
current primary owner */
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index cd44861..320419f 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -519,6 +519,14 @@ bool QDBusConnectionPrivate::handleMessage(const 
QDBusMessage &amsg)
     switch (amsg.type()) {
     case QDBusMessage::SignalMessage:
         handleSignal(amsg);
+        // Check local disconnected signal from libdbus
+        if (amsg.interface() == QDBusUtil::dbusInterfaceLocal()
+            && amsg.path() == QDBusUtil::dbusPathLocal()
+            && amsg.member() == QDBusUtil::disconnected()
+            && !QDBusMessagePrivate::isLocal(amsg)) {
+            while (!pendingCalls.isEmpty())
+                processFinishedCall(pendingCalls.first());
+        }
         // if there are any other filters in this DBusConnection,
         // let them see the signal too
         return false;
@@ -1767,10 +1775,16 @@ void 
QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
 
     QDBusMessage &msg = call->replyMessage;
     if (call->pending) {
-        // decode the message
-        DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
-        msg = QDBusMessagePrivate::fromDBusMessage(reply, 
connection->capabilities);
-        q_dbus_message_unref(reply);
+        // when processFinishedCall is called and pending call is not 
completed,
+        // it means we received disconnected signal from libdbus
+        if (q_dbus_pending_call_get_completed(call->pending)) {
+            // decode the message
+            DBusMessage *reply = 
q_dbus_pending_call_steal_reply(call->pending);
+            msg = QDBusMessagePrivate::fromDBusMessage(reply, 
connection->capabilities);
+            q_dbus_message_unref(reply);
+        } else {
+            msg = QDBusMessage::createError(QDBusError::Disconnected, 
QDBusUtil::disconnectedErrorMessage());
+        }
     }
     qDBusDebug() << connection << "got message reply:" << msg;
 
@@ -2070,8 +2084,8 @@ void 
QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void *
             pcall->pending = pending;
             q_dbus_pending_call_set_notify(pending, qDBusResultReceived, 
pcall, 0);
 
-            // DBus won't notify us when a peer disconnects so we need to 
track these ourselves
-            if (mode == QDBusConnectionPrivate::PeerMode)
+            // DBus won't notify us when a peer disconnects or server 
terminates so we need to track these ourselves
+            if (mode == QDBusConnectionPrivate::PeerMode || mode == 
QDBusConnectionPrivate::ClientMode)
                 pendingCalls.append(pcall);
 
             return;
diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h
index 8f5ae92..ca70ff9 100644
--- a/src/dbus/qdbusutil_p.h
+++ b/src/dbus/qdbusutil_p.h
@@ -155,6 +155,8 @@ namespace QDBusUtil
     { return QStringLiteral(DBUS_SERVICE_DBUS); }
     inline QString dbusPath()
     { return QStringLiteral(DBUS_PATH_DBUS); }
+    inline QString dbusPathLocal()
+    { return QStringLiteral(DBUS_PATH_LOCAL); }
     inline QString dbusInterface()
     {
         // it's the same string, but just be sure
@@ -165,8 +167,12 @@ namespace QDBusUtil
     { return QStringLiteral(DBUS_INTERFACE_PROPERTIES); }
     inline QString dbusInterfaceIntrospectable()
     { return QStringLiteral(DBUS_INTERFACE_INTROSPECTABLE); }
+    inline QString dbusInterfaceLocal()
+    { return QStringLiteral(DBUS_INTERFACE_LOCAL); }
     inline QString nameOwnerChanged()
     { return QStringLiteral("NameOwnerChanged"); }
+    inline QString disconnected()
+    { return QStringLiteral("Disconnected"); }
     inline QString disconnectedErrorMessage()
     { return QStringLiteral("Not connected to D-Bus server"); }
 }
diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp 
b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
index e91f87d..6c7e6b1 100644
--- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
+++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
@@ -1218,6 +1218,28 @@ void tst_QDBusConnection::callVirtualObjectLocal()
     QCOMPARE(obj.replyArguments, subPathReply.arguments());
 }
 
+void tst_QDBusConnection::pendingCallWhenDisconnected()
+{
+    QDBusServer *server = new QDBusServer;
+    QDBusConnection con = QDBusConnection::connectToPeer(server->address(), 
"disconnect");
+    QTestEventLoop::instance().enterLoop(2);
+    QVERIFY(!QTestEventLoop::instance().timeout());
+    QVERIFY(con.isConnected());
+
+    delete server;
+
+    // Make sure we call the method before we know it is disconnected.
+    QVERIFY(con.isConnected());
+    QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), 
"method");
+    QDBusPendingCall reply = con.asyncCall(message);
+
+    QTestEventLoop::instance().enterLoop(2);
+    QVERIFY(!con.isConnected());
+    QVERIFY(reply.isFinished());
+    QVERIFY(reply.isError());
+    QVERIFY(reply.error().type() == QDBusError::Disconnected);
+}
+
 QString MyObject::path;
 QString MyObjectWithoutInterface::path;
 QString MyObjectWithoutInterface::interface;
diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h 
b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h
index a53ba32..720e484 100644
--- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h
+++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h
@@ -121,6 +121,7 @@ private slots:
     void registerVirtualObject();
     void callVirtualObject();
     void callVirtualObjectLocal();
+    void pendingCallWhenDisconnected();
 
 public:
     QString serviceName() const { return 
"org.qtproject.Qt.Autotests.QDBusConnection"; }
-- 
2.6.2.2.g1b5ffa3

++++++ qtbase-opensource-src-5.5.1.tar.xz -> qtbase-opensource-src-5.6.0.tar.xz 
++++++
/work/SRC/openSUSE:Factory/libqt5-qtbase/qtbase-opensource-src-5.5.1.tar.xz 
/work/SRC/openSUSE:Factory/.libqt5-qtbase.new/qtbase-opensource-src-5.6.0.tar.xz
 differ: char 17, line 1

++++++ tell-the-truth-about-private-api.patch ++++++
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index aefd3ae..53a3f60 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -195,16 +195,18 @@
 
 
!header_module:unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!no_linker_version_script:!static
 {
     verscript = $${TARGET}.version
     QMAKE_LFLAGS += $${QMAKE_LFLAGS_VERSION_SCRIPT}$$verscript
 
+       private_api_headers = $$SYNCQT.PRIVATE_HEADER_FILES 
$$SYNCQT.QPA_HEADER_FILES
+
     internal_module {
-        verscript_content = "Qt_$${QT_MAJOR_VERSION}_PRIVATE_API { *; };"
+        verscript_content = 
"Qt_$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}_PRIVATE_API 
{ *; };"
     } else {
-        verscript_content = "Qt_$${QT_MAJOR_VERSION}_PRIVATE_API {" \
+        verscript_content = 
"Qt_$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}_PRIVATE_API 
{" \
                             "    qt_private_api_tag*;"
-        for(header, SYNCQT.PRIVATE_HEADER_FILES): \
+        for(header, private_api_headers): \
             verscript_content += "    @FILE:$${_PRO_FILE_PWD_}/$$header@"
         verscript_content += "};"
 
         current = Qt_$$QT_MAJOR_VERSION
         verscript_content += "$$current { *; };"
@@ -221,11 +223,11 @@
         # Add a post-processing step to replace the @FILE:filename@
         verscript_in = $${verscript}.in
         verscriptprocess.name = linker version script ${QMAKE_FILE_BASE}
         verscriptprocess.input = verscript_in
         verscriptprocess.CONFIG += no_link target_predeps
-        for(header, SYNCQT.PRIVATE_HEADER_FILES): \
+        for(header, private_api_headers)): \
             verscriptprocess.depends += $${_PRO_FILE_PWD_}/$$header
         verscriptprocess.output = $$verscript
         verscriptprocess.commands = perl $${PWD}/data/unix/findclasslist.pl < 
${QMAKE_FILE_IN} > $@
         silent:verscriptprocess.commands = @echo creating linker version 
script ${QMAKE_FILE_BASE} && $$verscriptprocess.commands
         QMAKE_EXTRA_COMPILERS += verscriptprocess

Reply via email to